UNPKG

@burglekitt/gmt

Version:

Temporal-based date and time utilities with timezone support and polyfill integration

57 lines (56 loc) 2.54 kB
import { Temporal } from "@js-temporal/polyfill"; import { isValidTime, isValidTimeDurationUnit } from "../validate/index.js"; import { getLargestTimeDurationUnit } from "./getLargestTimeDurationUnit.js"; /** * Return the difference between two PlainTime values in the requested unit. * * - Returns `null` for invalid inputs. * - Uses Temporal.PlainTime.until with `largestUnit` and extracts the requested unit. * * `smallestUnit`, `roundingIncrement`, and `roundingMode` control optional rounding of the result, * per Temporal's DifferenceOptions — e.g. `{ smallestUnit: "minute", roundingMode: "halfExpand" }` * rounds the difference to the nearest minute before extracting the requested unit. * - When `units` is an array, `smallestUnit` must not be coarser than the largest unit in the * array (e.g. `["minute", "second"]` with `smallestUnit: "hour"`) — this combination is * rejected by Temporal and returns null, same as other invalid input. * * @param time1 ISO PlainTime string for the start * @param time2 ISO PlainTime string for the end * @param units TimeDurationUnit | TimeDurationUnit[] to measure the difference * @param options optional: smallestUnit, roundingIncrement, roundingMode (Temporal.DifferenceOptions rounding controls) * @returns numeric difference in the requested unit, or null on invalid input * * @example diffTime("12:00:00", "14:30:00", "hour") // 2 * @example diffTime("invalid", "14:30:00", "hour") // null */ export function diffTime(time1, time2, units, options) { const validTimes = isValidTime(time1) && isValidTime(time2); const isSingleUnit = !Array.isArray(units); const validUnits = isSingleUnit ? isValidTimeDurationUnit(units) : units.every(isValidTimeDurationUnit); if (!validTimes || !validUnits) { return null; } try { const t1 = Temporal.PlainTime.from(time1); const t2 = Temporal.PlainTime.from(time2); const duration = t1.until(t2, { largestUnit: isSingleUnit ? units : getLargestTimeDurationUnit(units), smallestUnit: options?.smallestUnit, roundingIncrement: options?.roundingIncrement, roundingMode: options?.roundingMode, }); // craft record for units passed if (isSingleUnit) { return duration[units] ?? 0; } return units.reduce((result, unit) => { result[unit] = duration[unit] ?? 0; return result; }, {}); } catch { return null; } }