latest
mary-ext/pkg-date-fnsWorks with
•JSR Score100%•This package works with Cloudflare Workers, Node.js, Deno, Bun, Browsers




Downloads53/wk
•Published10 months ago (0.1.3)
small date utilities
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724/** * represents a day of the week as a numeric value (0 = Sunday, 6 = Saturday). */ export type DayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6; /** * returns the Unix timestamp in milliseconds for a given date. * @param date the date to convert. * @returns the Unix timestamp in milliseconds. */ /*#__NO_SIDE_EFFECTS__*/ export const toUnixMilliseconds = (date: Date): number => { return date.getTime(); }; /** * returns the Unix timestamp in seconds for a given date * @param date the date to convert. * @returns the Unix timestamp in seconds. */ /*#__NO_SIDE_EFFECTS__*/ export const toUnixSeconds = (date: Date): number => { return Math.floor(toUnixMilliseconds(date) / 1_000); }; /** * converts a date to an ISO 8601 date string (YYYY-MM-DD) in local timezone * @param date the date to format * @returns the formatted date string */ /*#__NO_SIDE_EFFECTS__*/ export const toISODateString = (date: Date): string => { return date.toLocaleDateString('sv-SE'); }; /** * converts a date to an ISO 8601 datetime string (YYYY-MM-DDTHH:mm:ss.sss) in local timezone * @param date the date to format * @returns the formatted datetime string */ /*#__NO_SIDE_EFFECTS__*/ export const toISODateTimeString = (date: Date): string => { return date.toLocaleString('sv-SE').replace(' ', 'T') + '.' + ('' + getMilliseconds(date)).padStart(3, '0'); }; /** * returns the milliseconds portion of a given date. * @param date the date to extract from. * @returns the milliseconds portion of the date. */ /*#__NO_SIDE_EFFECTS__*/ export const getMilliseconds = (date: Date): number => { return date.getMilliseconds(); }; /** * returns the seconds portion of a given date. * @param date the date to extract from. * @returns the seconds portion of the date. */ /*#__NO_SIDE_EFFECTS__*/ export const getSeconds = (date: Date): number => { return date.getSeconds(); }; /** * returns the minutes portion of a given date. * @param date the date to extract from. * @returns the minutes portion of the date. */ /*#__NO_SIDE_EFFECTS__*/ export const getMinutes = (date: Date): number => { return date.getMinutes(); }; /** * returns the hours portion of a given date. * @param date the date to extract from. * @returns the hours portion of the date. */ /*#__NO_SIDE_EFFECTS__*/ export const getHours = (date: Date): number => { return date.getHours(); }; /** * returns the day of the week for a given date (0 = Sunday, 6 = Saturday). * @param date the date to extract from. * @returns the day of the week as a number. */ /*#__NO_SIDE_EFFECTS__*/ export const getDayOfWeek = (date: Date): DayOfWeek => { return date.getDay() as DayOfWeek; }; /** * returns the day of the month for a given date. * @param date the date to extract from. * @returns the day of the month as a number. */ /*#__NO_SIDE_EFFECTS__*/ export const getDayOfMonth = (date: Date): number => { return date.getDate(); }; /** * returns the month portion of a given date (0 = January, 11 = December). * @param date the date to extract from. * @returns the month as a number. */ /*#__NO_SIDE_EFFECTS__*/ export const getMonth = (date: Date): number => { return date.getMonth(); }; /** * returns the year portion of a given date. * @param date the date to extract from. * @returns the year as a number. */ /*#__NO_SIDE_EFFECTS__*/ export const getYear = (date: Date): number => { return date.getFullYear(); }; /** * compares two dates and returns a number indicating their relative order, * in UTC time. * @template TDate * @param a the first date to compare. * @param b the second date to compare. * @returns -1 if a is before b, 1 if a is after b, or 0 if they are equal. */ /*#__NO_SIDE_EFFECTS__*/ export const compareUtcAsc = <TDate extends Date>(a: TDate, b: TDate): number => { const aMs = toUnixMilliseconds(a); const bMs = toUnixMilliseconds(b); if (aMs < bMs) { return -1; } if (aMs > bMs) { return 1; } return 0; }; /** * compares two dates and returns a number indicating their relative order, * in local time. * @template TDate * @param a the first date to compare. * @param b the second date to compare. * @returns -1 if a is before b, 1 if a is after b, or 0 if they are equal. */ /*#__NO_SIDE_EFFECTS__*/ export const compareLocalAsc = <TDate extends Date>(a: TDate, b: TDate): number => { const diff = getMilliseconds(a) - getMilliseconds(b) || getSeconds(a) - getSeconds(b) || getMinutes(a) - getMinutes(b) || getHours(a) - getHours(b) || getDayOfMonth(a) - getDayOfMonth(b) || getMonth(a) - getMonth(b) || getYear(a) - getYear(b); if (diff < 0) { return -1; } if (diff > 0) { return 1; } return 0; }; /** * checks if a date is before another date. * @template TDate * @param a the date to compare. * @param b the date to compare against. * @returns true if first date is before the second, false otherwise. */ /*#__NO_SIDE_EFFECTS__*/ export const isBeforeDate = <TDate extends Date>(a: TDate, b: TDate): boolean => { return a !== b && toUnixMilliseconds(a) < toUnixMilliseconds(b); }; /** * checks if a date is after another date. * @template TDate * @param a the date to compare. * @param b the date to compare against. * @returns true if the first date is after the second, false otherwise. */ /*#__NO_SIDE_EFFECTS__*/ export const isAfterDate = <TDate extends Date>(a: TDate, b: TDate): boolean => { return a !== b && toUnixMilliseconds(a) > toUnixMilliseconds(b); }; /** * checks if two dates are exactly the same. * @template TDate * @param a the first date to compare. * @param b the second date to compare. * @returns true if the two dates are the same, false otherwise. */ /*#__NO_SIDE_EFFECTS__*/ export const isSameDate = <TDate extends Date>(a: TDate, b: TDate): boolean => { return a === b || toUnixMilliseconds(a) === toUnixMilliseconds(b); }; /** * checks if two dates fall on the same calendar day. * @template TDate * @param a the first date to compare. * @param b the second date to compare. * @returns true if the two dates fall on the same calendar day, false otherwise. */ /*#__NO_SIDE_EFFECTS__*/ export const isSameCalendarDate = <TDate extends Date>(a: TDate, b: TDate): boolean => { if (a === b) { return true; } return ( getDayOfMonth(a) === getDayOfMonth(b) && getMonth(a) === getMonth(b) && getYear(a) === getYear(b) ); }; /** * checks if two dates fall in the same calendar month. * @template TDate * @param a the first date to compare. * @param b the second date to compare. * @returns true if the two dates are in the same month, false otherwise. */ /*#__NO_SIDE_EFFECTS__*/ export const isSameCalendarMonth = <TDate extends Date>(a: TDate, b: TDate): boolean => { if (a === b) { return true; } return ( getMonth(a) === getMonth(b) && getYear(a) === getYear(b) ); }; /** * checks if two dates fall in the same calendar year. * @template TDate * @param a the first date to compare. * @param b the second date to compare. * @returns true if the two dates are in the same year, false otherwise. */ /*#__NO_SIDE_EFFECTS__*/ export const isSameCalendarYear = <TDate extends Date>(a: TDate, b: TDate): boolean => { if (a === b) { return true; } return getYear(a) === getYear(b); }; /** * returns the earlier of two dates. * @template TDate * @param a the first date to compare. * @param b the second date to compare. * @returns the earlier of the two dates. */ /*#__NO_SIDE_EFFECTS__*/ export const min = <TDate extends Date>(a: TDate, b: TDate): TDate => { return isBeforeDate(a, b) ? a : b; }; /** * returns the later of two dates. * @template TDate * @param a the first date to compare. * @param b the second date to compare. * @returns the later of the two dates. */ /*#__NO_SIDE_EFFECTS__*/ export const max = <TDate extends Date>(a: TDate, b: TDate): TDate => { return isAfterDate(a, b) ? a : b; }; /** * clamps a date between a minimum and maximum range. * @template TDate * @param date the date to clamp. * @param min the minimum allowable date. * @param max the maximum allowable date. * @returns the clamped date. */ /*#__NO_SIDE_EFFECTS__*/ export const clamp = <TDate extends Date>( date: TDate, min: TDate | undefined, max: TDate | undefined, ): TDate => { if (min !== undefined && isBeforeDate(date, min)) { return min; } if (max !== undefined && isAfterDate(date, max)) { return max; } return date; }; /** * calculates the difference in milliseconds between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in milliseconds. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInMilliseconds = <TDate extends Date>(a: TDate, b: TDate): number => { return toUnixMilliseconds(a) - toUnixMilliseconds(b); }; /** * calculates the difference in seconds between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in seconds. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInSeconds = <TDate extends Date>(a: TDate, b: TDate): number => { return Math.trunc(differenceInMilliseconds(a, b) / 1_000); }; /** * calculates the difference in minutes between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in minutes. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInMinutes = <TDate extends Date>(a: TDate, b: TDate): number => { return Math.trunc(differenceInMilliseconds(a, b) / 60_000); }; /** * calculates the difference in hours between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in hours. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInHours = <TDate extends Date>(a: TDate, b: TDate): number => { return Math.trunc(differenceInMilliseconds(a, b) / 3_600_000); }; /** * calculates the difference in days between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in days. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInDays = <TDate extends Date>(a: TDate, b: TDate): number => { return Math.trunc(differenceInMilliseconds(a, b) / 86_400_000); }; /** * calculates the difference in calendar days between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in calendar days. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInCalendarDays = <TDate extends Date>(a: TDate, b: TDate): number => { return differenceInDays(startOfDay(a), startOfDay(b)); }; /** * calculates the difference in weeks between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in weeks. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInWeeks = <TDate extends Date>(a: TDate, b: TDate): number => { return Math.trunc(differenceInDays(a, b) / 7); }; /** * calculates the difference in calendar weeks between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in calendar weeks. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInCalendarWeeks = <TDate extends Date>(a: TDate, b: TDate): number => { return differenceInWeeks(startOfWeek(a), startOfWeek(b)); }; /** * calculates the difference in months between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in months. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInMonths = <TDate extends Date>(a: TDate, b: TDate): number => { return (getYear(a) - getYear(b)) * 12 + (getMonth(a) - getMonth(b)); }; /** * calculates the difference in calendar months between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in calendar months. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInCalendarMonths = <TDate extends Date>(a: TDate, b: TDate): number => { return differenceInMonths(startOfMonth(a), startOfMonth(b)); }; /** * calculates the difference in years between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in years. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInYears = <TDate extends Date>(a: TDate, b: TDate): number => { return getYear(a) - getYear(b); }; /** * calculates the difference in calendar years between two dates. * @template TDate * @param a the first date. * @param b the second date. * @returns the difference in calendar years. */ /*#__NO_SIDE_EFFECTS__*/ export const differenceInCalendarYears = <TDate extends Date>(a: TDate, b: TDate): number => { return differenceInYears(startOfYear(a), startOfYear(b)); }; type DateConstructor<TDate extends Date> = { new (value: number | string | TDate): TDate }; /** * creates a copy of a given date. * @template TDate * @param date the date to clone. * @returns a new date object with the same value as the input date. */ /*#__NO_SIDE_EFFECTS__*/ export const cloneDate = <TDate extends Date>(date: TDate): TDate => { return new (date.constructor as DateConstructor<TDate>)(date); }; /** * returns the start of the day for a given date. * @template TDate * @param date the date to find the start of the day for. * @returns a new date set to the start of the day. */ /*#__NO_SIDE_EFFECTS__*/ export const startOfDay = <TDate extends Date>(date: TDate): TDate => { const d = cloneDate(date); d.setHours(0, 0, 0, 0); return d; }; /** * returns the end of the day for a given date. * @template TDate * @param date the date to find the end of the day for. * @returns a new date set to the end of the day. */ /*#__NO_SIDE_EFFECTS__*/ export const endOfDay = <TDate extends Date>(date: TDate): TDate => { const d = cloneDate(date); d.setHours(23, 59, 59, 999); return d; }; /** * returns the start of the week for a given date. * @template TDate * @param date the date to find the start of the week for. * @returns a new date set to the start of the week. */ /*#__NO_SIDE_EFFECTS__*/ export const startOfWeek = <TDate extends Date>(date: TDate): TDate => { const d = cloneDate(date); d.setDate(getDayOfMonth(d) - getDayOfWeek(d)); d.setHours(0, 0, 0, 0); return d; }; /** * returns the end of the week for a given date. * @template TDate * @param date the date to find the end of the week for. * @returns a new date set to the end of the week. */ /*#__NO_SIDE_EFFECTS__*/ export const endOfWeek = <TDate extends Date>(date: TDate): TDate => { const d = cloneDate(date); d.setDate(getDayOfMonth(d) + (6 - getDayOfWeek(d))); d.setHours(23, 59, 59, 999); return d; }; /** * returns the start of the month for a given date. * @template TDate * @param date the date to find the start of the month for. * @returns a new date set to the start of the month. */ /*#__NO_SIDE_EFFECTS__*/ export const startOfMonth = <TDate extends Date>(date: TDate): TDate => { const d = cloneDate(date); d.setDate(1); d.setHours(0, 0, 0, 0); return d; }; /** * returns the end of the month for a given date. * @template TDate * @param date the date to find the end of the month for. * @returns a new date set to the end of the month. */ /*#__NO_SIDE_EFFECTS__*/ export const endOfMonth = <TDate extends Date>(date: TDate): TDate => { const d = cloneDate(date); d.setMonth(getMonth(d) + 1, 0); d.setHours(23, 59, 59, 999); return d; }; /** * returns the start of the year for a given date. * @template TDate * @param date the date to find the start of the year for. * @returns a new date set to the start of the year. */ /*#__NO_SIDE_EFFECTS__*/ export const startOfYear = <TDate extends Date>(date: TDate): TDate => { const d = cloneDate(date); d.setMonth(0, 1); d.setHours(0, 0, 0, 0); return d; }; /** * returns the end of the year for a given date. * @template TDate * @param date the date to find the end of the year for. * @returns a new date set to the end of the year. */ /*#__NO_SIDE_EFFECTS__*/ export const endOfYear = <TDate extends Date>(date: TDate): TDate => { const d = cloneDate(date); d.setMonth(11, 31); d.setHours(23, 59, 59, 999); return d; }; /** * adds a specified number of milliseconds to a date. * @template TDate * @param date the date to add milliseconds to. * @param milliseconds the number of milliseconds to add. * @returns a new date with the added milliseconds. */ /*#__NO_SIDE_EFFECTS__*/ export const addMilliseconds = <TDate extends Date>(date: TDate, milliseconds: number): TDate => { const d = cloneDate(date); d.setMilliseconds(getMilliseconds(d) + milliseconds); return d; }; /** * adds a specified number of seconds to a date. * @template TDate * @param date the date to add seconds to. * @param seconds the number of seconds to add. * @returns a new date with the added seconds. */ /*#__NO_SIDE_EFFECTS__*/ export const addSeconds = <TDate extends Date>(date: TDate, seconds: number): TDate => { const d = cloneDate(date); d.setSeconds(getSeconds(d) + seconds); return d; }; /** * adds a specified number of minutes to a date. * @template TDate * @param date the date to add minutes to. * @param minutes the number of minutes to add. * @returns a new date with the added minutes. */ /*#__NO_SIDE_EFFECTS__*/ export const addMinutes = <TDate extends Date>(date: TDate, minutes: number): TDate => { const d = cloneDate(date); d.setMinutes(getMinutes(d) + minutes); return d; }; /** * adds a specified number of hours to a date. * @template TDate * @param date the date to add hours to. * @param hours the number of hours to add. * @returns a new date with the added hours. */ /*#__NO_SIDE_EFFECTS__*/ export const addHours = <TDate extends Date>(date: TDate, hours: number): TDate => { const d = cloneDate(date); d.setHours(getHours(d) + hours); return d; }; /** * adds a specified number of days to a date. * @template TDate * @param date the date to add days to. * @param days the number of days to add. * @returns a new date with the added days. */ /*#__NO_SIDE_EFFECTS__*/ export const addDays = <TDate extends Date>(date: TDate, days: number): TDate => { const d = cloneDate(date); d.setDate(getDayOfMonth(d) + days); return d; }; /** * adds a specified number of months to a date. * @template TDate * @param date the date to add months to. * @param months the number of months to add. * @returns a new date with the added months. */ /*#__NO_SIDE_EFFECTS__*/ export const addMonths = <TDate extends Date>(date: TDate, months: number): TDate => { const d = cloneDate(date); d.setMonth(getMonth(d) + months); return d; }; /** * adds a specified number of years to a date. * @template TDate * @param date the date to add years to. * @param years the number of years to add. * @returns a new date with the added years. */ /*#__NO_SIDE_EFFECTS__*/ export const addYears = <TDate extends Date>(date: TDate, years: number): TDate => { const d = cloneDate(date); d.setFullYear(getYear(d) + years); return d; }; /** * returns the previous occurrence of a specific day of the week. * @template TDate * @param date the starting date. * @param day the target day of the week. * @returns a new date set to the previous occurrence of the specified day. */ /*#__NO_SIDE_EFFECTS__*/ export const previousDay = <TDate extends Date>(date: TDate, day: DayOfWeek): TDate => { let delta = day - getDayOfWeek(date); if (delta >= 0) { delta -= 7; } return addDays(date, delta); }; /** * returns the next occurrence of a specific day of the week. * @template TDate * @param date the starting date. * @param day the target day of the week. * @returns a new date set to the next occurrence of the specified day. */ /*#__NO_SIDE_EFFECTS__*/ export const nextDay = <TDate extends Date>(date: TDate, day: DayOfWeek): TDate => { let delta = day - getDayOfWeek(date); if (delta <= 0) { delta += 7; } return addDays(date, delta); };