@applicvision/js-toolbox
Version:
A collection of tools for modern JavaScript development
167 lines (157 loc) • 5.17 kB
JavaScript
export const YEAR = 'year';
export const MONTH = 'month';
export const DAY = 'day';
export const HOUR = 'hour';
export const MINUTE = 'minute';
export const SECOND = 'second';
export const MILLISECOND = 'millisecond';
export const YEARS = YEAR;
export const MONTHS = MONTH;
export const DAYS = DAY;
export const HOURS = HOUR;
export const MINUTES = MINUTE;
export const SECONDS = SECOND;
export const MILLISECONDS = MILLISECOND;
const units = [YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLISECOND]
function unitsFrom(unit) {
return units.slice(units.indexOf(unit))
}
const timeUnits = unitsFrom(HOUR)
class IzzaDate extends Date {
static get YEAR() { return YEAR };
static get MONTH() { return MONTH };
static get DAY() { return DAY };
static get YEARS() { return YEAR };
static get MONTHS() { return MONTH };
static get DAYS() { return DAY };
/**
* Add to a date by given amount in given unit.
* @param {number} amount Amont to add
* @param {'year'|'month'|'day'|'hour'|'minute'|'second'|'millisecond'} unit Unit to add to
* @param {...any} otherChanges Other changes, alternating `amount` and `unit`.
* @returns {IzzaDate}
*/
add(amount, unit, ...otherChanges) {
if (amount === undefined && unit === undefined) {
return this;
}
return this
.set(unit, this.get(unit) + amount)
.add(...otherChanges);
}
/**
* Set the value of a given unit.
* @param {'year'|'month'|'day'|'hour'|'minute'|'second'|'millisecond'} unit Unit to set
* @param {number} value The new value
*/
set(unit, value) {
switch (unit) {
case YEAR: this.setFullYear(value); break;
case MONTH: this.setMonth(value); break;
case DAY: this.setDate(value); break;
case HOUR: this.setHours(value); break
case MINUTE: this.setMinutes(value); break
case SECOND: this.setSeconds(value); break
case MILLISECOND: this.setMilliseconds(value); break
}
return this;
}
/**
* Get the date's value of a specific unit.
* @param {'year'|'month'|'day'|'hour'|'minute'|'second'|'millisecond'} unit Unit to get the value for
*/
get(unit) {
switch (unit) {
case YEAR: return this.getFullYear();
case MONTH: return this.getMonth();
case DAY: return this.getDate();
case HOUR: return this.getHours();
case MINUTE: return this.getMinutes();
case SECOND: return this.getSeconds();
case MILLISECOND: return this.getMilliseconds();
}
}
/**
* Subtract from a date by given amounts in given units.
* @param {...any} changes Repeating pattern of `amount` and `unit`.
*/
subtract(...changes) {
return this.add(...changes.map((value, index) => index % 2 ? value : -value));
}
/**
* Same as `.add`, but creates a copy before manipulating the date.
* Example: `date.dateByAdding(1, 'year', 2, 'months')`
* @param {...any} changes Repeating pattern of `amount` and `unit`.
*/
dateByAdding(...changes) {
return this.copy().add(...changes);
}
/**
* Same as `.set`, but creates a copy before manipulating the date.
* @param {'year'|'month'|'day'|'hour'|'minute'|'second'|'millisecond'} unit Unit to set
* @param {number} value The new value for the unit
*/
dateBySetting(unit, value) {
return this.copy().set(unit, value);
}
/**
* Returns a copy of the date.
*/
copy() {
return new IzzaDate(this)
}
/**
* Same as `.subtract`, but creates a copy before manupulating the date.
* Example: `date.dateBySutracting(1, 'year', 2, 'months')`
* @param {...any} changes Repeating patter of `amount` and `unit`.
*/
dateBySubtracting(...changes) {
return this.copy().subtract(...changes);
}
/**
* Checks if the date is earlier in the day than the `compareDate`.
* @param {Date} compareDate The date to compare with
*/
isEarlierInTheDay(compareDate) {
return timeUnits.some(unit => this.get(unit) < compareDate.get(unit))
}
/**
* Checks if the date is same time of day as the `compareDate`.
* @param {Date} compareDate The date to compare with
*/
isSameTimeOfDay(compareDate) {
return timeUnits.every(unit => this.get(unit) == compareDate.get(unit))
}
/**
* Returns object with values for the given units.
* @param {('year'|'month'|'day'|'hour'|'minute'|'second'|'millisecond')[]} [forUnits] the units to get the values for
*/
components(forUnits = units) {
return Object.fromEntries(forUnits.map(unit => [unit, this.get(unit)]))
}
/**
* Checks if the date is later in the day than the `compareDate`.
* @param {Date} compareDate The date to compare with
*/
isLaterInTheDay(compareDate) {
return timeUnits.some(unit => this.get(unit) > compareDate.get(unit))
}
/**
* Returns the number of days (integer) until `date`. Returns negative number if `date` is in the past.
* @param {Date} date Date to get days until
* @returns {number}
*/
daysUntil(date) {
const diff = date - this
return Math.floor(diff / (3600 * 1000 * 24)) + this.isLaterInTheDay(date)
}
/**
* Returns the number of days (integer) since `date`. Returns negative number if `date` is in the future.
* @param {Date} date Date to get the days since
* @returns {number}
*/
daysSince(date) {
return date.daysUntil(this)
}
}
export default IzzaDate;