UNPKG

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
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 };