UNPKG

tiinvo

Version:

A library of types and utilities for your TypeScript and JavaScript projects

144 lines (143 loc) 4.11 kB
//#region factories /** * Creates a `DateRange.t` between a starting date `start` and an ending date `end` (included). * * @example * * ```ts * import { DateRange } from 'tiinvo' * * const dr = DateRange.make(new Date('2020-01-01'), new Date('2020-01-03'), 'day'); * * Array.from(dr) // [new Date(2020, 0, 1), new Date(2020, 0, 2), new Date(2020, 0, 3)] * ``` * * @param start the starting date * @param end the ending date * @step the step to increment. It can be: * - `"year"` (default), increments by year * - `"month"`, increments by month * - `"day"`, increments by day * @group Factories * @since 4.0.0 */ export const make = (start, end, step = 'year') => { const direction = start > end ? -1 : 1; start = new Date(start); end = new Date(end); start.setHours(0); start.setMinutes(0); start.setSeconds(0); start.setMilliseconds(0); end.setHours(0); end.setMinutes(0); end.setSeconds(0); end.setMilliseconds(0); return { start, end, step, [Symbol.iterator]: () => { let current = new Date(start); let last = new Date(end); return { current, last, next() { if (direction > 0 ? current.getTime() <= last.getTime() : current.getTime() >= last.getTime()) { const value = new Date(current); switch (step) { case 'day': current.setDate(current.getDate() + direction); break; case 'month': current.setMonth(current.getMonth() + direction); break; case 'year': current.setFullYear(current.getFullYear() + direction); break; } return { done: false, value }; } else { return { done: true, value: last }; } } }; } }; }; //#endregion //#region guards /** * Checks if a parameter `x` is a `DateRange.t`. * * Start and end are included in check. * * @example * * ```ts * import { DateRange, Range } from 'tiinvo' * * DateRange.guard(0) // false * DateRange.guard(Range.make(0, 2)) // false * DateRange.guard(DateRange.make(new Date(), new Date())) // true * ``` * * @param x the value to check * @returns returns true if x is DateRange, false otherwise * @group Guardables * @since 4.0.0 */ export const guard = (x) => typeof x === 'object' && x !== null && 'start' in x && 'end' in x && 'step' in x && typeof x.step === 'string' && x.start instanceof Date && x.end instanceof Date; export function inRange(a, b) { if (guard(a) && !!b) { const c = new Date(b); c.setMilliseconds(0); c.setMinutes(0); c.setHours(0); return c >= a.start && c <= a.end; } return (b) => { const c = new Date(a); c.setMilliseconds(0); c.setMinutes(0); c.setHours(0); return c >= b.start && c <= b.end; }; } export function map(t, m) { const _map = (y, f) => { const out = []; for (const x of y) { out.push(f(x)); } return out; }; if (guard(t) && !!m) { return _map(t, m); } else if (!guard(t)) { return (b) => _map(b, t); } } //#endregion //#region serializables /** * Converts a `DateRange.t` to a `Date[]` array * * @example * * ```ts * import { DateRange } from 'tiinvo' * * const dr = DateRange.make(new Date('2020-01-01'), new Date('2020-01-03'), 'day'); * * DateRange.toArray(dr) // [new Date(2020, 0, 1), new Date(2020, 0, 2), new Date(2020, 0, 3)] * ``` * * @group Serializables * @since 4.0.0 */ export const toArray = Array.from; //#endregion