diff --git a/src/ap.ts b/src/ap.ts index caf96cf..177201b 100644 --- a/src/ap.ts +++ b/src/ap.ts @@ -1,4 +1,5 @@ import { dayPeriodMap, specDate, normStr } from "./common" +import type { LocalePeriod } from "./types" /** * Determines the correct value for am/pm by locale and memoizes it. @@ -7,24 +8,19 @@ import { dayPeriodMap, specDate, normStr } from "./common" */ export function ap(ampm: "am" | "pm", locale: string): string { const l = dayPeriodMap.get(locale) - if (l && l[ampm]) return l[ampm] as string + if (l?.[ampm]) return l[ampm] as string const specimen = new Date(specDate) specimen.setUTCHours(ampm === "am" ? 5 : 20) - const subparts = new Intl.DateTimeFormat(locale, { + const subParts = new Intl.DateTimeFormat(locale, { timeStyle: "full", timeZone: "UTC", hour12: true, }) .formatToParts(specimen) .map(normStr) - const period = subparts.find((part) => part.type === "dayPeriod") - if (period) { - const localePeriods: { am?: string; pm?: string } = l || {} - dayPeriodMap.set( - locale, - Object.assign(localePeriods, { [ampm]: period.value }) - ) - return period.value - } - return ampm + const period = subParts.find((part) => part.type === "dayPeriod") + if (!period) return ampm + const localePeriod: LocalePeriod = l || {} + dayPeriodMap.set(locale, Object.assign(localePeriod, { [ampm]: period.value })) + return period.value } diff --git a/src/common.ts b/src/common.ts index 58ff594..dbdefea 100644 --- a/src/common.ts +++ b/src/common.ts @@ -1,7 +1,6 @@ import { date } from "./date" import { ap } from "./ap" import type { - DateInput, NamedFormats, FormatPattern, FormatStyle, @@ -9,6 +8,7 @@ import type { FilledPart, Format, MaybeDateInput, + LocalePeriod, } from "./types" /** @@ -124,7 +124,7 @@ export const tokens = /* @__PURE__ */ new Map( /** * A map of locale’s am/pm. */ -export const dayPeriodMap: Map = new Map() +export const dayPeriodMap: Map = new Map() /** * An array of all available date styles. @@ -278,15 +278,19 @@ function createPartMap( if (hour12.length) addValues(hour12, true) if (hour24.length) addValues(hour24) - return valueParts.reduce((map, part) => { - map[part.type] = part.value - return map - }, {} as Record) + return valueParts.reduce( + (map, part) => { + map[part.type] = part.value + return map + }, + {} as Record + ) } /** * Converts minutes (300) to an ISO8601 compatible offset (+0400 or +04:00). * @param timeDiffInMins - The difference in minutes between two timezones. + * @param token * @returns */ export function minsToOffset(timeDiffInMins: number, token: string = "Z"): string { diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000..9a6b417 --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,6 @@ +/* Times in milliseconds */ +export const ONE_SECOND_MS = 1_000 +export const ONE_MINUTE_MS = 60_000 +export const ONE_HOUR_MS = 3_600_000 +export const ONE_DAY_MS = 86_400_000 +export const SEVEN_DAY_MS = 604_800_000 diff --git a/src/date.ts b/src/date.ts index 5e93826..b2d8a3d 100644 --- a/src/date.ts +++ b/src/date.ts @@ -9,7 +9,7 @@ import type { MaybeDateInput } from "./types" function normalize(date: string) { const matches = date.match(iso8601Match) if (matches && typeof matches[4] === "undefined") { - return (date += "T00:00:00") + return date + "T00:00:00" } return date } @@ -28,8 +28,6 @@ export function date(date?: MaybeDateInput): Date { return d } date = date.trim() - if (iso8601(date)) { - return new Date(normalize(date)) - } - throw new Error(`Non ISO 8601 compliant date (${date}).`) + if (!iso8601(date)) throw new Error(`Non ISO 8601 compliant date (${date}).`) + return new Date(normalize(date)) } diff --git a/src/dayOfYear.ts b/src/dayOfYear.ts index 28a6e63..85e212e 100644 --- a/src/dayOfYear.ts +++ b/src/dayOfYear.ts @@ -1,5 +1,6 @@ import { date } from "./date" import type { MaybeDateInput } from "./types" +import { ONE_DAY_MS } from "./constants" /** * Gets the what day of the year a given date is. For example, August 1st is @@ -11,6 +12,6 @@ export function dayOfYear(inputDate?: MaybeDateInput): number { return Math.round( (new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0).getTime() - new Date(d.getFullYear(), 0, 0).getTime()) / - 86400000 + ONE_DAY_MS ) } diff --git a/src/diffDays.ts b/src/diffDays.ts index 73669e5..28547c9 100644 --- a/src/diffDays.ts +++ b/src/diffDays.ts @@ -1,6 +1,7 @@ import { diffMilliseconds } from "./diffMilliseconds" import type { DateInput, MaybeDateInput } from "./types" import { diffRound, type DiffRoundingMethod } from "./diffRound" +import { ONE_DAY_MS } from "./constants" /** * Returns the difference between 2 dates in days. @@ -30,9 +31,5 @@ export function diffDays( dateB?: MaybeDateInput, roundingMethod?: DiffRoundingMethod ): number { - return diffRound( - // @ts-ignore - diffMilliseconds(dateA, dateB) / 86_400_000, // hour * 24 - roundingMethod - ) + return diffRound(diffMilliseconds(dateA, dateB) / ONE_DAY_MS, roundingMethod) } diff --git a/src/diffHours.ts b/src/diffHours.ts index 5f9bca3..3b76269 100644 --- a/src/diffHours.ts +++ b/src/diffHours.ts @@ -1,6 +1,7 @@ import { diffMilliseconds } from "./diffMilliseconds" import { diffRound, type DiffRoundingMethod } from "./diffRound" import type { DateInput, MaybeDateInput } from "./types" +import { ONE_HOUR_MS } from "./constants" /** * Returns the difference between 2 dates in hours. @@ -31,9 +32,5 @@ export function diffHours( dateB?: MaybeDateInput, roundingMethod?: DiffRoundingMethod ): number { - return diffRound( - //@ts-ignore - diffMilliseconds(dateA, dateB) / 3_600_000, // 1000 * 60 * 60 - roundingMethod - ) + return diffRound(diffMilliseconds(dateA, dateB) / ONE_HOUR_MS, roundingMethod) } diff --git a/src/diffMilliseconds.ts b/src/diffMilliseconds.ts index faa4c88..fc5a2f9 100644 --- a/src/diffMilliseconds.ts +++ b/src/diffMilliseconds.ts @@ -15,6 +15,13 @@ export function diffMilliseconds(dateA: DateInput, dateB?: MaybeDateInput): numb */ export function diffMilliseconds(dateA: MaybeDateInput, dateB: DateInput): number +/** + * Returns the difference between 2 dates in milliseconds. + * @param [dateA] - A date to compare with the right date or null to compare with the current time + * @param dateB - A date to compare with the left date or null to compare with the current time + */ +export function diffMilliseconds(dateA: MaybeDateInput, dateB?: MaybeDateInput): number + export function diffMilliseconds(dateA: MaybeDateInput, dateB?: MaybeDateInput): number { const left = date(dateA) const right = date(dateB) diff --git a/src/diffMinutes.ts b/src/diffMinutes.ts index 1fbabf4..16a69f4 100644 --- a/src/diffMinutes.ts +++ b/src/diffMinutes.ts @@ -1,6 +1,7 @@ import type { DateInput, MaybeDateInput } from "./types" import { diffMilliseconds } from "./diffMilliseconds" import { diffRound, type DiffRoundingMethod } from "./diffRound" +import { ONE_MINUTE_MS } from "./constants" /** * Returns the difference between 2 dates in minutes. @@ -31,9 +32,5 @@ export function diffMinutes( dateB?: MaybeDateInput, roundingMethod?: DiffRoundingMethod ): number { - return diffRound( - //@ts-ignore - diffMilliseconds(dateA, dateB) / 60_000, - roundingMethod - ) + return diffRound(diffMilliseconds(dateA, dateB) / ONE_MINUTE_MS, roundingMethod) } diff --git a/src/diffMonths.ts b/src/diffMonths.ts index fdb54e1..3522af6 100644 --- a/src/diffMonths.ts +++ b/src/diffMonths.ts @@ -8,6 +8,7 @@ import { monthDays } from "./monthDays" * @param [dateB] - A date to compare with the dateA date or nothing to compare with the current time */ export function diffMonths(dateA: DateInput, dateB?: MaybeDateInput): number + /** * Returns the difference between 2 dates in months. * @param [dateA] - A date to compare with the dateB date or null to compare with the current time @@ -15,12 +16,20 @@ export function diffMonths(dateA: DateInput, dateB?: MaybeDateInput): number */ export function diffMonths(dateA: MaybeDateInput, dateB: DateInput): number +/** + * Returns the difference between 2 dates in months. + * @param [dateA] - A date to compare with the dateB date or null to compare with the current time + * @param dateB - A date to compare with the dateA date or null to compare with the current time + */ +export function diffMonths(dateA: MaybeDateInput, dateB?: MaybeDateInput): number + export function diffMonths(dateA: MaybeDateInput, dateB?: MaybeDateInput): number { const l = date(dateA) const r = date(dateB) // if the dateB one is bigger, we switch them around as it's easier to do if (l < r) { const rs = diffMonths(r, l) + // Ensures we don't give back -0 return rs == 0 ? 0 : -rs } @@ -38,6 +47,6 @@ export function diffMonths(dateA: MaybeDateInput, dateB?: MaybeDateInput): numbe months-- } } - //ensures we don't give back -0 + // Ensures we don't give back -0 return months == 0 ? 0 : months } diff --git a/src/diffSeconds.ts b/src/diffSeconds.ts index 0be157d..968140d 100644 --- a/src/diffSeconds.ts +++ b/src/diffSeconds.ts @@ -1,6 +1,7 @@ import { diffMilliseconds } from "./diffMilliseconds" import { DiffRoundingMethod, diffRound } from "./diffRound" import type { DateInput, MaybeDateInput } from "./types" +import { ONE_SECOND_MS } from "./constants" /** * Returns the difference between 2 dates in seconds. @@ -31,9 +32,5 @@ export function diffSeconds( dateB?: MaybeDateInput, roundingMethod?: DiffRoundingMethod ): number { - return diffRound( - // @ts-ignore - diffMilliseconds(dateA, dateB) / 1000, - roundingMethod - ) + return diffRound(diffMilliseconds(dateA, dateB) / ONE_SECOND_MS, roundingMethod) } diff --git a/src/diffWeeks.ts b/src/diffWeeks.ts index 4e1b90b..b9410c2 100644 --- a/src/diffWeeks.ts +++ b/src/diffWeeks.ts @@ -1,6 +1,7 @@ import { diffMilliseconds } from "./diffMilliseconds" import { DateInput, MaybeDateInput } from "./types" import { diffRound, type DiffRoundingMethod } from "./diffRound" +import { SEVEN_DAY_MS } from "./constants" /** * Returns the difference between 2 dates in days. @@ -31,8 +32,5 @@ export function diffWeeks( dateB: DateInput, roundingMethod?: DiffRoundingMethod ): number { - return diffRound( - diffMilliseconds(dateA, dateB) / 604800000, // day * 7 - roundingMethod - ) + return diffRound(diffMilliseconds(dateA, dateB) / SEVEN_DAY_MS, roundingMethod) } diff --git a/src/diffYears.ts b/src/diffYears.ts index cf85af0..af11272 100644 --- a/src/diffYears.ts +++ b/src/diffYears.ts @@ -15,10 +15,7 @@ export function diffYears(dateA: DateInput, dateB?: MaybeDateInput): number */ export function diffYears(dateA: MaybeDateInput, dateB: DateInput): number export function diffYears(dateA: MaybeDateInput, dateB?: MaybeDateInput): number { - const r = Math.trunc( - //@ts-ignore - diffMonths(dateA, dateB) / 12 - ) - //ensures we don't give back -0 + const r = Math.trunc(diffMonths(dateA, dateB) / 12) + // Ensures we don't give back -0 return r == 0 ? 0 : r } diff --git a/src/format.ts b/src/format.ts index 7777b14..6010ed7 100644 --- a/src/format.ts +++ b/src/format.ts @@ -1,13 +1,7 @@ import { date } from "./date" import { parts } from "./parts" import { fill, getOffsetFormat } from "./common" -import type { - DateInput, - Format, - FormatOptions, - FormatStyle, - Part, -} from "./types" +import type { DateInput, Format, FormatOptions, Part } from "./types" import { offset } from "./offset" import { removeOffset } from "./removeOffset" import { deviceLocale } from "./deviceLocale" @@ -42,8 +36,10 @@ import { deviceTZ } from "./deviceTZ" * * @param inputDate - A date object or ISO 8601 string * @param format - A format + * @param locale + * @param genitive + * @param partFilter */ -export function format(options: FormatOptions): string export function format( inputDate: DateInput, format?: Format, @@ -60,10 +56,7 @@ export function format( ): string { let tz: string | undefined, forceOffset: string | undefined - if ( - typeof inputDateOrOptions === "object" && - !(inputDateOrOptions instanceof Date) - ) { + if (typeof inputDateOrOptions === "object" && !(inputDateOrOptions instanceof Date)) { // Extract options from the object. ;({ date: inputDateOrOptions, diff --git a/src/formatStr.ts b/src/formatStr.ts index dd8fe58..c608939 100644 --- a/src/formatStr.ts +++ b/src/formatStr.ts @@ -9,6 +9,8 @@ import type { Format, Part } from "./types" * ``` * @param format - A format string or object. * @param locale - A locale or en by default. + * @param escapeLiterals + * @param filterParts */ export function formatStr( format: Format, @@ -17,14 +19,11 @@ export function formatStr( filterParts: (part: Part) => boolean = () => true ): string { return parts(format, locale) - .filter(filterParts) - .reduce( - (f, p) => - (f += - escapeLiterals && p.partName === "literal" - ? escapeTokens(p.token) - : p.token), - "" - ) + .reduce((f, p) => { + if (!filterParts(p)) return f + return ( + f + (escapeLiterals && p.partName === "literal" ? escapeTokens(p.token) : p.token) + ) + }, "") .normalize("NFKC") } diff --git a/src/iso8601.ts b/src/iso8601.ts index fb70ed8..6847c06 100644 --- a/src/iso8601.ts +++ b/src/iso8601.ts @@ -4,7 +4,7 @@ * specificity. */ export const iso8601Match = - /^([0-9]{4})-([0-1][0-9])(?:-([0-3][0-9]))?(?:[T ]?([0-2][0-9])(?::([0-5][0-9]))?(?::([0-5][0-9]))?)?(?:\.[0-9]+)?(Z|(?:\+|\-)[0-9]{2}:?[0-9]{2})?$/ + /^([0-9]{4})-([0-1][0-9])(?:-([0-3][0-9]))?(?:[T ]?([0-2][0-9])(?::([0-5][0-9]))?(?::([0-5][0-9]))?)?(?:\.[0-9]+)?(Z|[+\-][0-9]{2}:?[0-9]{2})?$/ /** * True when the date string is valid ISO 8601. @@ -12,20 +12,19 @@ export const iso8601Match = */ export function iso8601(date: string): boolean { const matches = date.match(iso8601Match) - if (matches) { - const month = Number(matches[2]) - if (month < 1 || month > 12) return false + if (!matches) return false - if (typeof matches[3] !== undefined) { - const date = Number(matches[3]) - if (date < 1 || date > 31) return false - } - if (typeof matches[4] !== undefined) { - const hours = Number(matches[4]) - if (hours < 0 || hours > 23) return false - } + const month = Number(matches[2]) + if (month < 1 || month > 12) return false - return true + if (typeof matches[3] !== undefined) { + const date = Number(matches[3]) + if (date < 1 || date > 31) return false } - return false + if (typeof matches[4] !== undefined) { + const hours = Number(matches[4]) + if (hours < 0 || hours > 23) return false + } + + return true } diff --git a/src/nearestDay.ts b/src/nearestDay.ts index e7db1d4..fbc7263 100644 --- a/src/nearestDay.ts +++ b/src/nearestDay.ts @@ -17,37 +17,28 @@ export function nearestDay( search: (date: Date) => boolean, constraint: number | "month" | "week" | "year" = 7 ): Date | null { - let increments: number - let decrements: number const d = date(inputDate) - switch (constraint) { - case "month": - decrements = d.getDate() - increments = monthDays(d) - d.getDate() - break - case "week": - decrements = d.getDay() + 1 - increments = 6 - d.getDay() - break - case "year": - const total = yearDays(d) - const day = dayOfYear(d) - decrements = day - increments = total - day - break - default: - increments = decrements = constraint - } - - for (let i = 0; i <= increments || i < decrements; i++) { - if (i <= increments) { - const next = addDay(d, i) - if (search(next)) return next - } - if (i && i <= decrements) { - const prev = addDay(d, -i) - if (search(prev)) return prev + const [increments, decrements] = (() => { + switch (constraint) { + case "month": + return [monthDays(d) - d.getDate(), d.getDate()] + case "week": + return [6 - d.getDay(), d.getDay() + 1] + case "year": + const total = yearDays(d) + const day = dayOfYear(d) + return [total - day, day] + default: + return [constraint, constraint] } - } - return null + })() + + return ( + Array.from({ length: Math.max(increments, decrements) + 1 }, (_, i) => i) + .flatMap((i) => [ + i <= increments ? addDay(d, i) : null, + i && i <= decrements ? addDay(d, -i) : null, + ]) + .find((date) => date && search(date)) || null + ) } diff --git a/src/offset.ts b/src/offset.ts index 6dfbed2..e51aae5 100644 --- a/src/offset.ts +++ b/src/offset.ts @@ -1,7 +1,7 @@ import { date } from "./date" -import { normStr, minsToOffset, TimezoneToken } from "./common" +import { minsToOffset, normStr, TimezoneToken } from "./common" import { deviceTZ } from "./deviceTZ" -import type { DateInput, MaybeDateInput } from "./types" +import type { MaybeDateInput } from "./types" /** * Converts a date object from one timezone to that same time in UTC. This is @@ -42,9 +42,10 @@ function relativeTime(d: Date, timeZone: string): Date { * Returns the offset between two timezones on a given date. The results are * ISO8601 compatible offsets like -0800 or +0530. * - * @param [dateInput] - (default: current time) The date on which to determine the offset + * @param utcTime * @param [tzA] - (default: UTC) The second timezone to compare determine the offset between. * @param [tzB] - (default: device) The first timezone to compare determine the offset between. + * @param timeZoneToken */ export function offset( utcTime?: MaybeDateInput, @@ -52,7 +53,7 @@ export function offset( tzB = "device", timeZoneToken: TimezoneToken = "Z" ): string { - tzB = tzB === "device" ? deviceTZ() ?? "utc" : tzB + tzB = tzB === "device" ? (deviceTZ() ?? "utc") : tzB const d = date(utcTime) const timeA = relativeTime(d, tzA) const timeB = relativeTime(d, tzB) diff --git a/src/parse.ts b/src/parse.ts index 1296a1e..2231a16 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -1,5 +1,13 @@ import { date } from "./date" -import { validate, styles, fixedLength, four, two, validOffset, fixedLengthByOffset } from "./common" +import { + validate, + styles, + fixedLength, + four, + two, + validOffset, + fixedLengthByOffset, +} from "./common" import { formatStr } from "./formatStr" import { fourDigitYear } from "./fourDigitYear" import { ap } from "./ap" @@ -16,14 +24,10 @@ import type { } from "./types" export function parse(options: ParseOptions): Date | never -export function parse( - dateStr: string, - format?: Format, - locale?: string -): Date | never +export function parse(dateStr: string, format?: Format, locale?: string): Date | never /** * Parses a date string into a Date object using the given format. - * @param dateStr - A string representing a date. + * @param dateStrOrOptions * @param format - The format the given string is in. * @param locale - The locale to parse the string from. */ @@ -53,8 +57,7 @@ export function parse( ) } if (format === "ISO8601") return date(dateStr) - const genitive = - styles.includes(format as FormatStyle) || typeof format === "object" + const genitive = styles.includes(format as FormatStyle) || typeof format === "object" const formatParts = validate(parts(format, locale).filter(partFilter)) if (!formatParts.length) throw new Error("parse() requires a pattern.") let parsedParts @@ -158,10 +161,7 @@ export function parse( */ export function parseParts(dateStr: string, formatParts: Part[]): FilledPart[] { let i = 0 - const advance = (parts: Part[]): [Part, Part | undefined] => [ - parts[i++], - parts[i], - ] + const advance = (parts: Part[]): [Part, Part | undefined] => [parts[i++], parts[i]] let pos = 0 const parsed: FilledPart[] = [] let n: undefined | Part = undefined diff --git a/src/parts.ts b/src/parts.ts index 9ac53f3..348349c 100644 --- a/src/parts.ts +++ b/src/parts.ts @@ -9,7 +9,6 @@ import { clock12, } from "./common" import type { - ParseOptions, Format, Part, FormatStyle, @@ -47,18 +46,14 @@ export function parts(format: Format, locale: string): Part[] { } function validate(patterns: Part[]): Part[] { - const parts = patterns.map((part) => part.partName) - const deduped = new Set(parts) - if (parts.length > deduped.size) { - throw new Error(`Cannot reuse format tokens.`) + const uniquePatterns = new Set(patterns.map((part) => part.partName)).size + if (uniquePatterns < patterns.length) { + throw new Error("Cannot reuse format tokens.") } return patterns } - function createPart( - hour12: boolean, - [token, option, exp]: FormatPattern - ): Part { + function createPart(hour12: boolean, [token, option, exp]: FormatPattern): Part { const partName = Object.keys(option)[0] as Intl.DateTimeFormatPartTypes const partValue = option[partName] as string return { @@ -78,13 +73,11 @@ export function parts(format: Format, locale: string): Part[] { // Reset the format before re-checking const parts = validate( - found24Patterns.concat( - clock12.filter(testPattern).map(createPart.bind(null, true)) - ) + found24Patterns.concat(clock12.filter(testPattern).map(createPart.bind(null, true))) ) - const extractIndex = /^\{!(\d+)!\}$/ + const extractIndex = /^\{!(\d+)!}$/ return f - .split(/(\{!\d+!\})/) + .split(/(\{!\d+!})/) .map((match: string): Part => { const hasIndex = match.match(extractIndex) if (hasIndex) { @@ -107,10 +100,7 @@ export function parts(format: Format, locale: string): Part[] { * @param format - A date style like "full" or "short" * @param locale - The locale string */ -function styleParts( - format: FormatStyle | FormatStyleObj, - locale: string -): Part[] { +function styleParts(format: FormatStyle | FormatStyleObj, locale: string): Part[] { const options: Intl.DateTimeFormatOptions = { timeZone: "UTC", } @@ -141,8 +131,7 @@ function styleParts( if (formatPattern === undefined) return const partValue = formatPattern[1][partName] if (!partValue) return - if (!formatPattern[2]) - formatPattern[2] = new RegExp(`${formatPattern[0]}`, "g") + if (!formatPattern[2]) formatPattern[2] = new RegExp(`${formatPattern[0]}`, "g") return { option: { [partName]: partValue }, partName, @@ -161,6 +150,9 @@ function styleParts( * * @param partName - The part name to guess for, like 'year' or 'month' * @param partValue - The current value, it is assumed this is the smallest denom. + * @param locale + * @param hour + * @param options */ function guessPattern( partName: T, @@ -214,7 +206,6 @@ function guessPattern( default: return undefined } - /* eslint-enable @typescript-eslint/no-non-null-assertion */ } /** @@ -240,16 +231,16 @@ function partStyle( const partStyles: NamedFormatOption[] = ["long", "short", "narrow"] const formats: Partial = {} for (let i = 0; i < 12; i++) { - date.setMonth(0 + i) + date.setMonth(i) if (i in weekdays) date.setDate(weekdays[i]) date.setUTCHours(8 + i) for (const style of partStyles) { const segments = new Intl.DateTimeFormat( locale, - parts.reduce( - (options, part) => Object.assign(options, { [part]: style }), - { hour12: true, timeZone: "UTC" } - ) + parts.reduce((options, part) => Object.assign(options, { [part]: style }), { + hour12: true, + timeZone: "UTC", + }) ) .formatToParts(date) .map(normStr) diff --git a/src/range.ts b/src/range.ts index d209d42..75edc8c 100644 --- a/src/range.ts +++ b/src/range.ts @@ -5,16 +5,10 @@ import type { FormatToken } from "./types" * Returns an array of options for a given token in a given locale. * @param token - Get the full range of options for a given token * @param locale - The locale to fetch the options for. + * @param genitive */ -export function range( - token: FormatToken, - locale = "en", - genitive = false -): string[] { - const r: (n: number, c: (index: number) => string | number) => string[] = ( - n, - c - ) => +export function range(token: FormatToken, locale = "en", genitive = false): string[] { + const r: (n: number, c: (index: number) => string | number) => string[] = (n, c) => Array(n) .fill("") .map((_, i) => `${c(i)}`) @@ -27,13 +21,9 @@ export function range( }) // MMM and MMMM if (token.startsWith("M")) - return range("MM").map((m) => - format(`2000-${m}-05`, token, locale, genitive) - ) + return range("MM").map((m) => format(`2000-${m}-05`, token, locale, genitive)) if (token.startsWith("d")) - return r(7, (i) => `0${i + 2}`).map((d) => - format(`2022-10-${d}`, token, locale) - ) + return r(7, (i) => `0${i + 2}`).map((d) => format(`2022-10-${d}`, token, locale)) if (token === "a") return [ap("am", locale).toLowerCase(), ap("pm", locale).toLowerCase()] if (token === "A") @@ -42,8 +32,7 @@ export function range( const year = new Date().getFullYear() return r(120, (i) => i + 1).reduce( (ranges, i) => { - if (i !== "120") - ranges.push(format(`${year + Number(i)}-06-06`, token, locale)) + if (i !== "120") ranges.push(format(`${year + Number(i)}-06-06`, token, locale)) ranges.unshift(format(`${year - Number(i)}-06-06`, token, locale)) return ranges }, diff --git a/src/removeOffset.ts b/src/removeOffset.ts index e2c6dd6..50ac78e 100644 --- a/src/removeOffset.ts +++ b/src/removeOffset.ts @@ -1,5 +1,5 @@ import { applyOffset } from "./applyOffset" -import type { DateInput, MaybeDateInput } from "./types" +import type { MaybeDateInput } from "./types" /** * Inverts the offset and applies it to the given date, returning a new date. diff --git a/src/types.ts b/src/types.ts index 293b674..c216060 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,6 +3,11 @@ */ export type DateInput = Date | string +/** + * The locale period used in the day period map. + */ +export type LocalePeriod = { am?: string; pm?: string } + /** * The date format used as a maybe input value. Either a date, ISO8601 string or null for current time */ diff --git a/src/tzDate.ts b/src/tzDate.ts index af70d4f..009404d 100644 --- a/src/tzDate.ts +++ b/src/tzDate.ts @@ -1,7 +1,7 @@ import { offset } from "./offset" import { applyOffset } from "./applyOffset" import { date } from "./date" -import { DateInput, MaybeDateInput } from "./types" +import { MaybeDateInput } from "./types" /** * Creates a date object for the input date at the given timezone. For example diff --git a/src/yearDays.ts b/src/yearDays.ts index 45fb34d..4173ee7 100644 --- a/src/yearDays.ts +++ b/src/yearDays.ts @@ -1,5 +1,6 @@ import { date } from "./date" import type { MaybeDateInput } from "./types" +import { ONE_DAY_MS } from "./constants" /** * Get the number of days in the given date’s year. @@ -10,6 +11,6 @@ export function yearDays(inputDate?: MaybeDateInput): number { return ( (new Date(d.getFullYear() + 1, 0, 0).getTime() - new Date(d.getFullYear(), 0, 0).getTime()) / - 86400000 + ONE_DAY_MS ) }