tiinvo
Version:
A library of types and utilities for your TypeScript and JavaScript projects
144 lines (143 loc) • 4.11 kB
JavaScript
//#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