UNPKG

@thi.ng/date

Version:

Datetime types, relative dates, math, iterators, composable formatters, locales

118 lines (117 loc) 3.22 kB
import { DAY, HOUR, MINUTE, SECOND } from "./api.js"; import { ensureEpoch } from "./checks.js"; import { dateTime, ensureDateTime } from "./datetime.js"; import { EN_LONG, EN_SHORT } from "./i18n/en.js"; const parseRelative = (offset, base) => { offset = offset.toLowerCase(); const epoch = dateTime(base); switch (offset) { case "today": return epoch; case "tomorrow": epoch.incDay(); return epoch; case "yesterday": epoch.decDay(); return epoch; default: { let idx = __findIndex(EN_SHORT.days, offset); if (idx < 0) { idx = __findIndex(EN_LONG.days, offset); } if (idx >= 0) { do { epoch.incDay(); } while (epoch.toDate().getDay() != idx); return epoch; } const match = /^(an? |next |[-+]?\d+\s?)((ms|milli(?:(s?|seconds?)))|s(?:(ecs?|econds?))?|min(?:(s|utes?))?|h(?:ours?)?|d(?:ays?)?|w(?:eeks?)?|mo(?:nths?)?|q(?:uarters?)?|y(?:ears?)?)(\s+ago)?$/.exec( offset ); return match ? relative( __parseNum(match[1], !!match[7]), __parsePeriod(match[2]), base ) : void 0; } } }; const __findIndex = (items, x) => items.findIndex((y) => y.toLowerCase() === x); const __parseNum = (x, past) => (x === "next " || x === "a " || x === "an " ? 1 : Number(x)) * (past ? -1 : 1); const __parsePeriod = (x) => { x = x !== "s" && x !== "ms" && x.endsWith("s") ? x.substring(0, x.length - 1) : x; return { ms: "t", milli: "t", millisecond: "t", sec: "s", second: "s", min: "m", minute: "m", hour: "h", day: "d", week: "w", mo: "M", month: "M", quarter: "q", year: "y" }[x] || x; }; const relative = (num, period, base = dateTime()) => dateTime(base).add(num, period); const difference = (a, b) => ensureEpoch(a) - ensureEpoch(b); const absDifference = (a, b) => Math.abs(difference(a, b)); const decomposeDifference = (a, b = /* @__PURE__ */ new Date()) => { const dur = ensureEpoch(a) - ensureEpoch(b); let abs = Math.abs(dur); const milli = abs % SECOND; abs -= milli; const sec = abs % MINUTE; abs -= sec; const min = abs % HOUR; abs -= min; const hour = abs % DAY; abs -= hour; const parts = [ Math.sign(dur), 0, // year 0, // month 0, // day hour / HOUR, min / MINUTE, sec / SECOND, milli ]; if (!abs) return parts; const diff = (a2, b2) => { const months2 = (b2.y - a2.y) * 12 + (b2.M - a2.M); const bstart = +a2.add(months2, "M"); let frac = +b2 - bstart; frac /= frac < 0 ? bstart - +a2.add(months2 - 1, "M") : +a2.add(months2 + 1, "M") - bstart; return -(months2 + frac) || 0; }; const aa = ensureDateTime(a, "d"); const bb = ensureDateTime(b, "d"); const months = Math.abs(aa.d < bb.d ? -diff(bb, aa) : diff(aa, bb)) | 0; const days = (start, end) => Math.abs( +start.withPrecision("d").add(months, "M") - +end.withPrecision("d") ) / DAY; parts[1] = months / 12 | 0; parts[2] = months % 12; parts[3] = dur < 0 ? days(aa, bb) : days(bb, aa); return parts; }; export { absDifference, decomposeDifference, difference, parseRelative, relative };