@burglekitt/gmt
Version:
Temporal-based date and time utilities with timezone support and polyfill integration
63 lines (62 loc) • 2.31 kB
JavaScript
/**
* Singular DateTimeUnit to its `Temporal.Duration` field name.
*
* Example lookups:
* - DURATION_FIELD_BY_UNIT.day => "days"
* - DURATION_FIELD_BY_UNIT.nanosecond => "nanoseconds"
*/
const DURATION_FIELD_BY_UNIT = {
year: "years",
month: "months",
week: "weeks",
day: "days",
hour: "hours",
minute: "minutes",
second: "seconds",
millisecond: "milliseconds",
microsecond: "microseconds",
nanosecond: "nanoseconds",
};
/**
* Return the start of the specified date-time `unit` for a `Temporal.ZonedDateTime`.
*
* - Always uses Monday as the week start (consistent with `startOfZoned` semantics).
* - Day-and-below units truncate by instant via `round({ roundingMode: "trunc" })`, which
* resolves DST correctly — a local day whose midnight is skipped starts at 01:00.
* - Does NOT validate the unit — caller ensures it is a DateTimeUnit.
*
* @param source Temporal.ZonedDateTime to truncate
* @param unit DateTimeUnit to truncate to
* @returns Temporal.ZonedDateTime at the start of the specified unit
*/
export function getStartOfZonedUnit(source, unit) {
switch (unit) {
case "year":
return source
.with({ month: 1, day: 1 })
.round({ smallestUnit: "day", roundingMode: "trunc" });
case "month":
return source
.with({ day: 1 })
.round({ smallestUnit: "day", roundingMode: "trunc" });
case "week":
return source
.subtract({ days: source.dayOfWeek - 1 })
.round({ smallestUnit: "day", roundingMode: "trunc" });
default:
return source.round({ smallestUnit: unit, roundingMode: "trunc" });
}
}
/**
* Extract the whole-unit span from a `Temporal.Duration` measured with `largestUnit: unit`.
*
* - Floors the field so a partial trailing amount never inflates a boundary count.
* - Does NOT validate the unit — caller ensures the duration was measured in it.
*
* @param duration Temporal.Duration produced by `until({ largestUnit: unit })`
* @param unit DateTimeUnit the duration was measured in
* @returns whole number of units spanned
*/
export function getUnitSpan(duration, unit) {
return Math.floor(duration[DURATION_FIELD_BY_UNIT[unit]]);
}