date-vir
Version:
Easy and explicit dates and times.
125 lines (124 loc) • 3.42 kB
JavaScript
import { DurationUnit, flattenUnitSelection, roundDuration, } from '@date-vir/duration';
import { toLuxonDateTime } from '../full-date/luxon-date-time-conversion.js';
const conversionAccuracies = {
[DurationUnit.Years]: 'longterm',
[DurationUnit.Quarters]: 'longterm',
[DurationUnit.Months]: 'longterm',
[DurationUnit.Weeks]: 'casual',
[DurationUnit.Days]: 'casual',
[DurationUnit.Hours]: 'casual',
[DurationUnit.Minutes]: 'casual',
[DurationUnit.Seconds]: 'casual',
[DurationUnit.Milliseconds]: 'casual',
};
function getHighestPriorityConversionAccuracy(units) {
if (units.some((unit) => conversionAccuracies[unit] === 'longterm')) {
return 'longterm';
}
else {
return 'casual';
}
}
/**
* Diffs two dates and returns the diff in the specified unit or units. When a multiple units are
* provided with the `units` input property, an array is returned with the full diff duration
* contained in each entry in the requested unit.
*
* Note: when years, quarters, or months are used for the unit, "long term" durations are used to
* calculate the diff. See more details here:
* https://moment.github.io/luxon/#/math?id=casual-vs-longterm-conversion-accuracy
*
* @category Calculation
* @example
*
* ```ts
* import {diffDates, DurationUnit} from 'date-vir';
*
* const exampleDate: FullDate = {
* year: 2024,
* month: 1,
* day: 5,
* hour: 1,
* minute: 1,
* second: 1,
* millisecond: 1,
* timezone: 'UTC',
* };
*
* // get the diff in days
* diffDates({start: exampleDate, end: {...exampleDate, day: 6}}, {days: true}); // {days: 1}
* // get the full diff separately in days and also years
* diffDates(
* {
* start: exampleDate,
* end: {
* ...exampleDate,
* day: exampleDate.day + 1,
* hour: exampleDate.hour + 3,
* },
* },
* {
* days: true,
* hours: true,
* },
* );
* // {days: 1, hours: 3}
* ```
*/
export function diffDates({ start, end, },
/** Which units the output should contain. */
units, options = {}) {
const luxonDateStart = toLuxonDateTime(start);
const luxonDateEnd = toLuxonDateTime(end);
const selectedUnits = flattenUnitSelection(units);
const conversionAccuracy = getHighestPriorityConversionAccuracy(selectedUnits);
const additiveDiff = luxonDateEnd
.diff(luxonDateStart, selectedUnits, {
conversionAccuracy,
})
.toObject();
return roundDuration(additiveDiff, options);
}
/**
* Checks if `fullDate` is after `relativeTo`.
*
* @category Calculation
* @example
*
* ```ts
* import {isDateAfter, type FullDate} from 'date-vir';
*
* const exampleDate: FullDate = {
* year: 2024,
* month: 1,
* day: 5,
* hour: 1,
* minute: 1,
* second: 1,
* millisecond: 1,
* timezone: 'UTC',
* };
*
* isDateAfter({
* fullDate: exampleDate,
* relativeTo: {
* ...exampleDate,
* year: 1900,
* },
* }); // `true`
*
* isDateAfter({
* fullDate: exampleDate,
* relativeTo: {
* ...exampleDate,
* year: 3000,
* },
* }); // `false`
* ```
*/
export function isDateAfter({ relativeTo, fullDate, }) {
return (diffDates({
start: relativeTo,
end: fullDate,
}, { milliseconds: true }).milliseconds > 0);
}