UNPKG

@helpwave/hightide

Version:

helpwave's component and theming library

1 lines 14.3 kB
{"version":3,"sources":["../../src/util/array.ts","../../src/util/date.ts"],"sourcesContent":["export const equalSizeGroups = <T>(array: T[], groupSize: number): T[][] => {\n if (groupSize <= 0) {\n console.warn(`group size should be greater than 0: groupSize = ${groupSize}`)\n return [[...array]]\n }\n\n const groups = []\n for (let i = 0; i < array.length; i += groupSize) {\n groups.push(array.slice(i, Math.min(i + groupSize, array.length)))\n }\n return groups\n}\n\nexport type RangeOptions = {\n /** Whether the range can be defined empty via end < start without a warning */\n allowEmptyRange: boolean,\n stepSize: number,\n exclusiveStart: boolean,\n exclusiveEnd: boolean,\n}\n\nconst defaultRangeOptions: RangeOptions = {\n allowEmptyRange: false,\n stepSize: 1,\n exclusiveStart: false,\n exclusiveEnd: true,\n}\n\n/**\n * @param endOrRange The end value or a range [start, end], end is exclusive\n * @param options the options for defining the range\n */\nexport const range = (endOrRange: number | [number, number], options?: Partial<RangeOptions>): number[] => {\n const { allowEmptyRange, stepSize, exclusiveStart, exclusiveEnd } = { ...defaultRangeOptions, ...options }\n let start = 0\n let end: number\n if (typeof endOrRange === 'number') {\n end = endOrRange\n } else {\n start = endOrRange[0]\n end = endOrRange[1]\n }\n if (!exclusiveEnd) {\n end -= 1\n }\n if (exclusiveStart) {\n start += 1\n }\n\n if (end - 1 < start) {\n if (!allowEmptyRange) {\n console.warn(`range: end (${end}) < start (${start}) should be allowed explicitly, set options.allowEmptyRange to true`)\n }\n return []\n }\n return Array.from({ length: end - start }, (_, index) => index * stepSize + start)\n}\n\n/** Finds the closest match\n * @param list The list of all possible matches\n * @param firstCloser Return whether item1 is closer than item2\n */\nexport const closestMatch = <T>(list: T[], firstCloser: (item1: T, item2: T) => boolean) => {\n return list.reduce((item1, item2) => {\n return firstCloser(item1, item2) ? item1 : item2\n })\n}\n\n/**\n * returns the item in middle of a list and its neighbours before and after\n * e.g. [1,2,3,4,5,6] for item = 1 would return [5,6,1,2,3]\n */\nexport const getNeighbours = <T>(list: T[], item: T, neighbourDistance: number = 2) => {\n const index = list.indexOf(item)\n const totalItems = neighbourDistance * 2 + 1\n if (list.length < totalItems) {\n console.warn('List is to short')\n return list\n }\n\n if (index === -1) {\n console.error('item not found in list')\n return list.splice(0, totalItems)\n }\n\n let start = index - neighbourDistance\n if (start < 0) {\n start += list.length\n }\n const end = (index + neighbourDistance + 1) % list.length\n\n const result: T[] = []\n let ignoreOnce = list.length === totalItems\n for (let i = start; i !== end || ignoreOnce; i = (i + 1) % list.length) {\n result.push(list[i]!)\n if (end === i && ignoreOnce) {\n ignoreOnce = false\n }\n }\n return result\n}\n\nexport const createLoopingListWithIndex = <T>(list: T[], startIndex: number = 0, length: number = 0, forwards: boolean = true) => {\n if (length < 0) {\n console.warn(`createLoopingList: length must be >= 0, given ${length}`)\n } else if (length === 0) {\n length = list.length\n }\n\n const returnList: [number, T][] = []\n\n if (forwards) {\n for (let i = startIndex; returnList.length < length; i = (i + 1) % list.length) {\n returnList.push([i, list[i]!])\n }\n } else {\n for (let i = startIndex; returnList.length < length; i = i === 0 ? i = list.length - 1 : i - 1) {\n returnList.push([i, list[i]!])\n }\n }\n\n return returnList\n}\n\nexport const createLoopingList = <T>(list: T[], startIndex: number = 0, length: number = 0, forwards: boolean = true) => {\n return createLoopingListWithIndex(list, startIndex, length, forwards).map(([_, item]) => item)\n}\n\nexport const ArrayUtil = {\n unique: <T>(list: T[]): T[] => {\n const seen = new Set<T>()\n return list.filter((item) => {\n if (seen.has(item)) {\n return false\n }\n seen.add(item)\n return true\n })\n },\n\n difference: <T>(list: T[], removeList: T[]): T[] => {\n const remove = new Set<T>(removeList)\n return list.filter((item) => !remove.has(item))\n }\n}\n","import { equalSizeGroups } from './array'\n\nexport const monthsList = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'] as const\nexport type Month = typeof monthsList[number]\n\nexport const weekDayList = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'] as const\nexport type WeekDay = typeof weekDayList[number]\n\nexport const formatDate = (date: Date) => {\n const year = date.getFullYear().toString().padStart(4, '0')\n const month = (date.getMonth() + 1).toString().padStart(2, '0')\n const day = (date.getDate()).toString().padStart(2, '0')\n return `${year}-${month}-${day}`\n}\n\nexport const formatDateTime = (date: Date) => {\n const dateString = formatDate(date)\n const hours = date.getHours().toString().padStart(2, '0')\n const minutes = date.getMinutes().toString().padStart(2, '0')\n return `${dateString}T${hours}:${minutes}`\n}\n\nexport const getDaysInMonth = (year: number, month: number): number => {\n const lastDayOfMonth = new Date(year, month + 1, 0)\n return lastDayOfMonth.getDate()\n}\n\nexport type Duration = {\n years?: number,\n months?: number,\n days?: number,\n hours?: number,\n minutes?: number,\n seconds?: number,\n milliseconds?: number,\n}\n\nexport const changeDuration = (date: Date, duration: Duration, isAdding?: boolean): Date => {\n const {\n years = 0,\n months = 0,\n days = 0,\n hours = 0,\n minutes = 0,\n seconds = 0,\n milliseconds = 0,\n } = duration\n\n // Check ranges\n if (years < 0) {\n console.error(`Range error years must be greater than 0: received ${years}`)\n return new Date(date)\n }\n if (months < 0 || months > 11) {\n console.error(`Range error month must be 0 <= month <= 11: received ${months}`)\n return new Date(date)\n }\n if (days < 0) {\n console.error(`Range error days must be greater than 0: received ${days}`)\n return new Date(date)\n }\n if (hours < 0 || hours > 23) {\n console.error(`Range error hours must be 0 <= hours <= 23: received ${hours}`)\n return new Date(date)\n }\n if (minutes < 0 || minutes > 59) {\n console.error(`Range error minutes must be 0 <= minutes <= 59: received ${minutes}`)\n return new Date(date)\n }\n if (seconds < 0 || seconds > 59) {\n console.error(`Range error seconds must be 0 <= seconds <= 59: received ${seconds}`)\n return new Date(date)\n }\n if (milliseconds < 0) {\n console.error(`Range error seconds must be greater than 0: received ${milliseconds}`)\n return new Date(date)\n }\n\n const multiplier = isAdding ? 1 : -1\n\n const newDate = new Date(date)\n\n newDate.setFullYear(newDate.getFullYear() + multiplier * years)\n\n newDate.setMonth(newDate.getMonth() + multiplier * months)\n\n newDate.setDate(newDate.getDate() + multiplier * days)\n\n newDate.setHours(newDate.getHours() + multiplier * hours)\n\n newDate.setMinutes(newDate.getMinutes() + multiplier * minutes)\n\n newDate.setSeconds(newDate.getSeconds() + multiplier * seconds)\n\n newDate.setMilliseconds(newDate.getMilliseconds() + multiplier * milliseconds)\n\n return newDate\n}\n\nexport const addDuration = (date: Date, duration: Duration): Date => {\n return changeDuration(date, duration, true)\n}\n\nexport const subtractDuration = (date: Date, duration: Duration): Date => {\n return changeDuration(date, duration, false)\n}\n\nexport const getBetweenDuration = (startDate: Date, endDate: Date): Duration => {\n const durationInMilliseconds = endDate.getTime() - startDate.getTime()\n\n const millisecondsInSecond = 1000\n const millisecondsInMinute = 60 * millisecondsInSecond\n const millisecondsInHour = 60 * millisecondsInMinute\n const millisecondsInDay = 24 * millisecondsInHour\n const millisecondsInMonth = 30 * millisecondsInDay // Rough estimation, can be adjusted\n\n const years = Math.floor(durationInMilliseconds / (365.25 * millisecondsInDay))\n const months = Math.floor(durationInMilliseconds / millisecondsInMonth)\n const days = Math.floor(durationInMilliseconds / millisecondsInDay)\n const hours = Math.floor((durationInMilliseconds % millisecondsInDay) / millisecondsInHour)\n const seconds = Math.floor((durationInMilliseconds % millisecondsInHour) / millisecondsInSecond)\n const milliseconds = durationInMilliseconds % millisecondsInSecond\n\n return {\n years,\n months,\n days,\n hours,\n seconds,\n milliseconds,\n }\n}\n\n/** Checks if a given date is in the range of two dates\n *\n * An undefined value for startDate or endDate means no bound for the start or end respectively\n */\nexport const isInTimeSpan = (value: Date, startDate?: Date, endDate?: Date): boolean => {\n if (startDate && endDate) {\n console.assert(startDate <= endDate)\n return startDate <= value && value <= endDate\n } else if (startDate) {\n return startDate <= value\n } else if (endDate) {\n return endDate >= value\n } else {\n return true\n }\n}\n\n/** Compare two dates on the year, month, day */\nexport const equalDate = (date1: Date, date2: Date) => {\n return date1.getFullYear() === date2.getFullYear()\n && date1.getMonth() === date2.getMonth()\n && date1.getDate() === date2.getDate()\n}\n\nexport const getWeeksForCalenderMonth = (date: Date, weekStart: WeekDay, weeks: number = 6) => {\n const month = date.getMonth()\n const year = date.getFullYear()\n\n const dayList: Date[] = []\n let currentDate = new Date(year, month, 1) // Start of month\n const weekStartIndex = weekDayList.indexOf(weekStart)\n\n // Move the current day to the week before\n while (currentDate.getDay() !== weekStartIndex) {\n currentDate = subtractDuration(currentDate, { days: 1 })\n }\n\n while (dayList.length < 7 * weeks) {\n const date = new Date(currentDate)\n date.setHours(date.getHours(), date.getMinutes()) // To make sure we are not overwriting the time\n dayList.push(date)\n currentDate = addDuration(currentDate, { days: 1 })\n }\n\n // weeks\n return equalSizeGroups(dayList, 7)\n}\n"],"mappings":"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","names":["date"]}