@thi.ng/date
Version:
Datetime types, relative dates, math, iterators, composable formatters, locales
118 lines (117 loc) • 3.22 kB
JavaScript
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
};