dt-i18n
Version:
A lightweight, modular JavaScript/TypeScript date and time utility with built-in internationalization (i18n) support for many languages.
410 lines (409 loc) • 11.1 kB
JavaScript
import D from "./locales/en.es.js";
function w(r, e) {
const t = String(r);
return !e || e.length === 0 ? t : t.replace(/\d/g, (a) => e[parseInt(a, 10)]);
}
function p(r, e, t) {
const { year: a, month: n, dayOfMonth: i, dayOfWeek: h, hours: s, minutes: o, seconds: d } = r, c = {
// Year
YYYY: String(a),
YY: String(a).slice(-2),
// Month
MMMM: t.months[n],
// Full month name
MM: String(n + 1).padStart(2, "0"),
// Month as two digits
M: String(n + 1),
// Month as one digit
// MS: locale.months[month].substring(0, 3), // Short month name Or add `monthsShort`
// Day
DDDD: t.weekdays[h],
// Full weekday name
DD: String(i).padStart(2, "0"),
// Days of the month as two digits
D: String(i),
// Days of the month as one digit
// DS: locale.weekdays[dayOfWeek].substring(0, 3), // Or add `weekdaysShort`
// Hour
HH: String(s).padStart(2, "0"),
// 24-hour - 2 digits
H: String(s),
// 24-hour - 1 digit
hh: String(s % 12 || 12).padStart(2, "0"),
// 12-hour - 2 digits
h: String(s % 12 || 12),
// 12-hour - 1 digit
// Minute
mm: String(o).padStart(2, "0"),
// Minutes as two digits
m: String(o),
// Minutes as one digit
// Second
ss: String(d).padStart(2, "0"),
// Seconds as two digits
s: String(d),
// Seconds as one digit
// AM/PM
A: s >= 12 ? "PM" : "AM",
// Uppercase AM/PM
a: s >= 12 ? "pm" : "am"
// Lowercase AM/PM
}, m = /YYYY|YY|MMMM|MM|M|DDDD|DD|D|HH|H|hh|h|mm|m|ss|s|A|a/g, g = e.replace(m, (l) => c[l] || l);
return w(g, t.numbers);
}
function b(r, e) {
if (!e)
return {
year: r.getFullYear(),
month: r.getMonth(),
dayOfMonth: r.getDate(),
dayOfWeek: r.getDay(),
hours: r.getHours(),
minutes: r.getMinutes(),
seconds: r.getSeconds()
};
const n = new Intl.DateTimeFormat("en-US", {
timeZone: e,
hour12: !1,
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
weekday: "long"
// We need the weekday name to calculate the day of the week index
}).formatToParts(r).reduce((s, o) => (s[o.type] = o.value, s), {}), h = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"].indexOf(n.weekday);
return {
year: parseInt(n.year, 10),
month: parseInt(n.month, 10) - 1,
// Intl gives 1-12, we need 0-11
dayOfMonth: parseInt(n.day, 10),
dayOfWeek: h,
// Intl can sometimes return '24' for midnight, so we correct it to '0'.
hours: parseInt(n.hour, 10) === 24 ? 0 : parseInt(n.hour, 10),
minutes: parseInt(n.minute, 10),
seconds: parseInt(n.second, 10)
};
}
const y = 1e3, k = y * 60, Y = k * 60, S = Y * 24, f = S * 365.25;
class T {
milliseconds;
constructor(e) {
this.milliseconds = e;
}
/**
* Gets the duration in a specific unit of time.
* @param unit The unit to get the duration in (e.g., 'days', 'hours').
* @returns The duration as a number.
*/
as(e) {
switch (e) {
case "second":
case "seconds":
return this.milliseconds / y;
case "minute":
case "minutes":
return this.milliseconds / k;
case "hour":
case "hours":
return this.milliseconds / Y;
case "day":
case "days":
return this.milliseconds / S;
// Note: Months are tricky due to variable lengths. This is a simple approximation.
case "month":
case "months":
return this.milliseconds / (f / 12);
case "year":
case "years":
return this.milliseconds / f;
default:
return this.milliseconds;
}
}
}
function H(r, e, t) {
const a = /YYYY|YY|MMMM|MM|M|DDDD|DD|D|HH|H|hh|h|mm|m|ss|s|A|a/g, n = [], i = e.replace(a, (o) => {
switch (n.push(o), o) {
case "YYYY":
return "(\\d{4})";
case "YY":
return "(\\d{2})";
case "MM":
case "DD":
case "HH":
case "hh":
case "mm":
case "ss":
return "(\\d{2})";
case "M":
case "D":
case "H":
case "h":
case "m":
case "s":
return "(\\d{1,2})";
case "A":
return "(AM|PM)";
case "a":
return "(am|pm)";
case "MMMM":
return `(${t.months.join("|")})`;
case "DDDD":
return `(${t.weekdays.join("|")})`;
default:
return o;
}
}), h = r.match(new RegExp(`^${i}$`, "i"));
if (!h)
return /* @__PURE__ */ new Date(NaN);
const s = {};
return n.forEach((o, d) => {
const c = h[d + 1];
switch (o) {
case "YYYY":
s.year = +c;
break;
case "YY":
s.year = +c < 70 ? 2e3 + +c : 1900 + +c;
break;
case "MM":
case "M":
s.month = +c;
break;
case "MMMM":
const m = t.months.findIndex((g) => g.toLowerCase() === c.toLowerCase());
m > -1 && (s.month = m + 1);
break;
case "DD":
case "D":
s.day = +c;
break;
case "HH":
case "H":
s.hour = +c;
break;
case "hh":
case "h":
s.hour = +c;
break;
case "mm":
case "m":
s.minute = +c;
break;
case "ss":
case "s":
s.second = +c;
break;
case "A":
case "a":
s.ampm = c.toLowerCase();
break;
}
}), s.ampm && s.hour !== void 0 && (s.ampm === "pm" && s.hour < 12 && (s.hour += 12), s.ampm === "am" && s.hour === 12 && (s.hour = 0)), new Date(
s.year || 1970,
(s.month || 1) - 1,
// Date constructor needs a 0-based month
s.day || 1,
s.hour || 0,
s.minute || 0,
s.second || 0
);
}
class u {
date;
currentLocale = D;
timezone = void 0;
// --- 1. CONSTRUCTOR ---
constructor(e, t, a) {
let n, i;
if (typeof t == "string") {
const h = a || D;
n = H(String(e), t, h), i = h;
} else
n = new Date(e ?? Date.now()), i = t;
this.date = isNaN(n.getTime()) ? /* @__PURE__ */ new Date() : n, this.currentLocale = i || D;
}
// --- 2. CONFIGURATION METHODS ---
locale(e) {
return this.currentLocale = e, this;
}
tz(e) {
return this.timezone = e, this;
}
// --- 3. MANIPULATION METHODS ---
add(e, t) {
const a = new Date(this.date);
switch (t) {
case "year":
case "years":
a.setFullYear(a.getFullYear() + e);
break;
case "month":
case "months":
a.setMonth(a.getMonth() + e);
break;
case "day":
case "days":
a.setDate(a.getDate() + e);
break;
case "hour":
case "hours":
a.setHours(a.getHours() + e);
break;
case "minute":
case "minutes":
a.setMinutes(a.getMinutes() + e);
break;
case "second":
case "seconds":
a.setSeconds(a.getSeconds() + e);
break;
}
return this.date = a, this;
}
subtract(e, t) {
return this.add(-e, t);
}
startOf(e) {
const t = new Date(this.date);
switch (e) {
case "year":
case "years":
t.setMonth(0, 1), t.setHours(0, 0, 0, 0);
break;
case "month":
case "months":
t.setDate(1), t.setHours(0, 0, 0, 0);
break;
case "day":
case "days":
t.setHours(0, 0, 0, 0);
break;
case "hour":
case "hours":
t.setMinutes(0, 0, 0);
break;
case "minute":
case "minutes":
t.setSeconds(0, 0);
break;
case "second":
case "seconds":
t.setMilliseconds(0);
break;
}
return this.date = t, this;
}
endOf(e) {
const t = new Date(this.date);
switch (e) {
case "year":
case "years":
t.setFullYear(t.getFullYear() + 1, 0, 0), t.setHours(23, 59, 59, 999), t.setDate(0);
break;
case "month":
case "months":
t.setMonth(t.getMonth() + 1, 0), t.setHours(23, 59, 59, 999);
break;
case "day":
case "days":
t.setHours(23, 59, 59, 999);
break;
case "hour":
case "hours":
t.setMinutes(59, 59, 999);
break;
case "minute":
case "minutes":
t.setSeconds(59, 999);
break;
case "second":
case "seconds":
t.setMilliseconds(999);
break;
}
return this.date = t, this;
}
// --- 4. QUERY & COMPARISON METHODS ---
isBefore(e) {
const t = e instanceof u ? e.toDate() : new Date(e);
return this.date.getTime() < t.getTime();
}
isAfter(e) {
const t = e instanceof u ? e.toDate() : new Date(e);
return this.date.getTime() > t.getTime();
}
isSameDay(e) {
const t = e instanceof u ? e.toDate() : new Date(e);
return this.date.getFullYear() === t.getFullYear() && this.date.getMonth() === t.getMonth() && this.date.getDate() === t.getDate();
}
isSameMonth(e) {
const t = e instanceof u ? e.toDate() : new Date(e);
return this.date.getFullYear() === t.getFullYear() && this.date.getMonth() === t.getMonth();
}
diff(e) {
const t = e instanceof u ? e.toDate() : new Date(e), a = this.date.getTime() - t.getTime();
return new T(a);
}
// --- 5. GETTER & UTILITY METHODS ---
toDate() {
return this.date;
}
dayOfYear() {
const e = new Date(this.date.getFullYear(), 0, 0), t = this.date.getTime() - e.getTime() + (e.getTimezoneOffset() - this.date.getTimezoneOffset()) * 60 * 1e3, a = 1e3 * 60 * 60 * 24;
return Math.floor(t / a);
}
weekOfYear() {
const e = new Date(this.date.getFullYear(), 0, 1), t = Math.floor((this.date.getTime() - e.getTime()) / (1440 * 60 * 1e3));
return Math.ceil((t + e.getDay() + 1) / 7);
}
quarter() {
return Math.floor(this.date.getMonth() / 3) + 1;
}
// --- 6. DISPLAY & OUTPUT METHODS ---
calendar() {
const e = this.startOf("month").toDate(), t = e.getDay(), a = M(e).subtract(t, "days"), n = [];
let i = a;
for (let h = 0; h < 6; h++) {
const s = [];
for (let o = 0; o < 7; o++)
s.push(M(i.toDate(), this.currentLocale)), i = i.add(1, "day");
n.push(s);
}
return n;
}
format(e) {
const t = b(this.date, this.timezone);
return p(t, e, this.currentLocale);
}
}
class O {
start;
end;
constructor(e, t) {
e.isAfter(t) ? (this.start = t, this.end = e) : (this.start = e, this.end = t);
}
/**
* Checks if a given date is within the interval (inclusive).
* @param date The date to check.
* @returns True if the date is within the interval.
*/
contains(e) {
const t = this.start.toDate().getTime(), a = this.end.toDate().getTime(), n = e instanceof u ? e.toDate().getTime() : new Date(e).getTime();
return n >= t && n <= a;
}
/**
* Returns the duration of the interval.
* @returns A Duration object representing the length of the interval.
*/
toDuration() {
return this.end.diff(this.start);
}
}
const M = (r, e, t) => new u(r, e, t);
M.interval = (r, e) => new O(r, e);
export {
M as dt
};