UNPKG

@byloth/core

Version:

An unopinionated collection of useful functions and classes that I use widely in all my projects. 🔧

274 lines (243 loc) • 6.04 kB
/* eslint-disable @typescript-eslint/prefer-literal-enum-member */ import { RangeException, SmartIterator } from "../models/index.js"; /** * An enumeration that represents the time units and their conversion factors. * It can be used as utility to express time values in a more * readable way or to convert time values between different units. * * --- * * @example * ```ts * setTimeout(() => { [...] }, 5 * TimeUnit.Minute); * ``` */ export enum TimeUnit { /** * A millisecond: the base time unit. */ Millisecond = 1, /** * A second: 1000 milliseconds. */ Second = 1_000, /** * A minute: 60 seconds. */ Minute = 60 * Second, /** * An hour: 60 minutes. */ Hour = 60 * Minute, /** * A day: 24 hours. */ Day = 24 * Hour, /** * A week: 7 days. */ Week = 7 * Day, /** * A month: 30 days. */ Month = 30 * Day, /** * A year: 365 days. */ Year = 365 * Day } /** * An enumeration that represents the days of the week. * It can be used as utility to identify the days of the week when working with dates. * * --- * * @example * ```ts * const today = new Date(); * if (today.getUTCDay() === WeekDay.Sunday) * { * // Today is Sunday. Do something... * } * ``` */ export enum WeekDay { /** * Sunday */ Sunday = 0, /** * Monday */ Monday = 1, /** * Tuesday */ Tuesday = 2, /** * Wednesday */ Wednesday = 3, /** * Thursday */ Thursday = 4, /** * Friday */ Friday = 5, /** * Saturday */ Saturday = 6 } /** * An utility function that calculates the difference between two dates. * The difference can be expressed in different time units. * * --- * * @example * ```ts * const start = new Date("2025-01-01"); * const end = new Date("2025-01-31"); * * dateDifference(start, end, TimeUnit.Minute); // 43200 * ``` * * --- * * @param start The start date. * @param end The end date. * @param unit The time unit to express the difference. `TimeUnit.Day` by default. * * @returns The difference between the two dates in the specified time unit. */ export function dateDifference(start: number | string | Date, end: number | string | Date, unit = TimeUnit.Day): number { let _round: (value: number) => number; start = new Date(start); end = new Date(end); if (start < end) { _round = Math.floor; } else { _round = Math.ceil; } return _round((end.getTime() - start.getTime()) / unit); } /** * An utility function that generates an iterator over a range of dates. * The step between the dates can be expressed in different time units. * * --- * * @example * ```ts * const start = new Date("2025-01-01"); * const end = new Date("2025-01-31"); * * for (const date of dateRange(start, end, TimeUnit.Week)) * { * date.toISOString().slice(8, 10); // "01", "08", "15", "22", "29" * } * ``` * * --- * * @param start The start date (included). * @param end * The end date (excluded). * * Must be greater than the start date. Otherwise, a {@link RangeException} will be thrown. * * @param step The time unit to express the step between the dates. `TimeUnit.Day` by default. * * @returns A {@link SmartIterator} object that generates the dates in the range. */ export function dateRange(start: number | string | Date, end: number | string | Date, step = TimeUnit.Day) : SmartIterator<Date> { start = new Date(start); end = new Date(end); if (start >= end) { throw new RangeException("The end date must be greater than the start date."); } return new SmartIterator<Date>(function* () { const endTime = end.getTime(); let unixTime: number = start.getTime(); while (unixTime < endTime) { yield new Date(unixTime); unixTime += step; } }); } /** * An utility function that rounds a date to the nearest time unit. * The rounding can be expressed in different time units. * * --- * * @example * ```ts * const date = new Date("2025-01-01T12:34:56.789Z"); * * dateRound(date, TimeUnit.Hour); // 2025-01-01T12:00:00.000Z * ``` * * --- * * @param date The date to round. * @param unit * The time unit to express the rounding. `TimeUnit.Day` by default. * * Must be greater than a millisecond and less than or equal to a day. * Otherwise, a {@link RangeException} will be thrown. * * @returns The rounded date. */ export function dateRound(date: number | string | Date, unit = TimeUnit.Day): Date { if (unit <= TimeUnit.Millisecond) { throw new RangeException( "Rounding a timestamp by milliseconds or less makes no sense." + "Use the timestamp value directly instead." ); } if (unit > TimeUnit.Day) { throw new RangeException( "Rounding by more than a day leads to unexpected results. " + "Consider using other methods to round dates by weeks, months or years." ); } date = new Date(date); return new Date(Math.floor(date.getTime() / unit) * unit); } /** * An utility function that gets the week of a date. * The first day of the week can be optionally specified. * * --- * * @example * ```ts * const date = new Date("2025-01-01"); * * getWeek(date, WeekDay.Monday); // 2024-12-30 * ``` * * --- * * @param date The date to get the week of. * @param firstDay The first day of the week. `WeekDay.Sunday` by default. * * @returns The first day of the week of the specified date. */ export function getWeek(date: number | string | Date, firstDay = WeekDay.Sunday): Date { date = new Date(date); const startCorrector = 7 - firstDay; const weekDayIndex = (date.getUTCDay() + startCorrector) % 7; const firstDayTime = date.getTime() - (TimeUnit.Day * weekDayIndex); return dateRound(new Date(firstDayTime)); }