Spaces:
Runtime error
Runtime error
| import { TZDate } from "@date-fns/tz"; | |
| import { addDays, addMonths, addWeeks, addYears, differenceInCalendarDays, differenceInCalendarMonths, eachMonthOfInterval, eachYearOfInterval, endOfISOWeek, endOfMonth, endOfWeek, endOfYear, format, getISOWeek, getMonth, getWeek, getYear, isAfter, isBefore, isDate, isSameDay, isSameMonth, isSameYear, max, min, setMonth, setYear, startOfDay, startOfISOWeek, startOfMonth, startOfWeek, startOfYear, } from "date-fns"; | |
| import { endOfBroadcastWeek } from "../helpers/endOfBroadcastWeek.js"; | |
| import { startOfBroadcastWeek } from "../helpers/startOfBroadcastWeek.js"; | |
| import { enUS } from "../locale/en-US.js"; | |
| /** | |
| * A wrapper class around [date-fns](http://date-fns.org) that provides utility | |
| * methods for date manipulation and formatting. | |
| * | |
| * @since 9.2.0 | |
| * @example | |
| * const dateLib = new DateLib({ locale: es }); | |
| * const newDate = dateLib.addDays(new Date(), 5); | |
| */ | |
| export class DateLib { | |
| /** | |
| * Creates an instance of `DateLib`. | |
| * | |
| * @param options Configuration options for the date library. | |
| * @param overrides Custom overrides for the date library functions. | |
| */ | |
| constructor(options, overrides) { | |
| /** | |
| * Reference to the built-in Date constructor. | |
| * | |
| * @deprecated Use `newDate()` or `today()`. | |
| */ | |
| this.Date = Date; | |
| /** | |
| * Creates a new `Date` object representing today's date. | |
| * | |
| * @since 9.5.0 | |
| * @returns A `Date` object for today's date. | |
| */ | |
| this.today = () => { | |
| if (this.overrides?.today) { | |
| return this.overrides.today(); | |
| } | |
| if (this.options.timeZone) { | |
| return TZDate.tz(this.options.timeZone); | |
| } | |
| return new this.Date(); | |
| }; | |
| /** | |
| * Creates a new `Date` object with the specified year, month, and day. | |
| * | |
| * @since 9.5.0 | |
| * @param year The year. | |
| * @param monthIndex The month (0-11). | |
| * @param date The day of the month. | |
| * @returns A new `Date` object. | |
| */ | |
| this.newDate = (year, monthIndex, date) => { | |
| if (this.overrides?.newDate) { | |
| return this.overrides.newDate(year, monthIndex, date); | |
| } | |
| if (this.options.timeZone) { | |
| return new TZDate(year, monthIndex, date, this.options.timeZone); | |
| } | |
| return new Date(year, monthIndex, date); | |
| }; | |
| /** | |
| * Adds the specified number of days to the given date. | |
| * | |
| * @param date The date to add days to. | |
| * @param amount The number of days to add. | |
| * @returns The new date with the days added. | |
| */ | |
| this.addDays = (date, amount) => { | |
| return this.overrides?.addDays | |
| ? this.overrides.addDays(date, amount) | |
| : addDays(date, amount); | |
| }; | |
| /** | |
| * Adds the specified number of months to the given date. | |
| * | |
| * @param date The date to add months to. | |
| * @param amount The number of months to add. | |
| * @returns The new date with the months added. | |
| */ | |
| this.addMonths = (date, amount) => { | |
| return this.overrides?.addMonths | |
| ? this.overrides.addMonths(date, amount) | |
| : addMonths(date, amount); | |
| }; | |
| /** | |
| * Adds the specified number of weeks to the given date. | |
| * | |
| * @param date The date to add weeks to. | |
| * @param amount The number of weeks to add. | |
| * @returns The new date with the weeks added. | |
| */ | |
| this.addWeeks = (date, amount) => { | |
| return this.overrides?.addWeeks | |
| ? this.overrides.addWeeks(date, amount) | |
| : addWeeks(date, amount); | |
| }; | |
| /** | |
| * Adds the specified number of years to the given date. | |
| * | |
| * @param date The date to add years to. | |
| * @param amount The number of years to add. | |
| * @returns The new date with the years added. | |
| */ | |
| this.addYears = (date, amount) => { | |
| return this.overrides?.addYears | |
| ? this.overrides.addYears(date, amount) | |
| : addYears(date, amount); | |
| }; | |
| /** | |
| * Returns the number of calendar days between the given dates. | |
| * | |
| * @param dateLeft The later date. | |
| * @param dateRight The earlier date. | |
| * @returns The number of calendar days between the dates. | |
| */ | |
| this.differenceInCalendarDays = (dateLeft, dateRight) => { | |
| return this.overrides?.differenceInCalendarDays | |
| ? this.overrides.differenceInCalendarDays(dateLeft, dateRight) | |
| : differenceInCalendarDays(dateLeft, dateRight); | |
| }; | |
| /** | |
| * Returns the number of calendar months between the given dates. | |
| * | |
| * @param dateLeft The later date. | |
| * @param dateRight The earlier date. | |
| * @returns The number of calendar months between the dates. | |
| */ | |
| this.differenceInCalendarMonths = (dateLeft, dateRight) => { | |
| return this.overrides?.differenceInCalendarMonths | |
| ? this.overrides.differenceInCalendarMonths(dateLeft, dateRight) | |
| : differenceInCalendarMonths(dateLeft, dateRight); | |
| }; | |
| /** | |
| * Returns the months between the given dates. | |
| * | |
| * @param interval The interval to get the months for. | |
| */ | |
| this.eachMonthOfInterval = (interval) => { | |
| return this.overrides?.eachMonthOfInterval | |
| ? this.overrides.eachMonthOfInterval(interval) | |
| : eachMonthOfInterval(interval); | |
| }; | |
| /** | |
| * Returns the years between the given dates. | |
| * | |
| * @since 9.11.1 | |
| * @param interval The interval to get the years for. | |
| * @returns The array of years in the interval. | |
| */ | |
| this.eachYearOfInterval = (interval) => { | |
| const years = this.overrides?.eachYearOfInterval | |
| ? this.overrides.eachYearOfInterval(interval) | |
| : eachYearOfInterval(interval); | |
| // Remove duplicates that may happen across DST transitions (e.g., "America/Sao_Paulo") | |
| // See https://github.com/date-fns/tz/issues/72 | |
| const uniqueYears = new Set(years.map((d) => this.getYear(d))); | |
| if (uniqueYears.size === years.length) { | |
| // No duplicates, return as is | |
| return years; | |
| } | |
| // Rebuild the array to ensure one date per year | |
| const yearsArray = []; | |
| uniqueYears.forEach((y) => { | |
| yearsArray.push(new Date(y, 0, 1)); | |
| }); | |
| return yearsArray; | |
| }; | |
| /** | |
| * Returns the end of the broadcast week for the given date. | |
| * | |
| * @param date The original date. | |
| * @returns The end of the broadcast week. | |
| */ | |
| this.endOfBroadcastWeek = (date) => { | |
| return this.overrides?.endOfBroadcastWeek | |
| ? this.overrides.endOfBroadcastWeek(date) | |
| : endOfBroadcastWeek(date, this); | |
| }; | |
| /** | |
| * Returns the end of the ISO week for the given date. | |
| * | |
| * @param date The original date. | |
| * @returns The end of the ISO week. | |
| */ | |
| this.endOfISOWeek = (date) => { | |
| return this.overrides?.endOfISOWeek | |
| ? this.overrides.endOfISOWeek(date) | |
| : endOfISOWeek(date); | |
| }; | |
| /** | |
| * Returns the end of the month for the given date. | |
| * | |
| * @param date The original date. | |
| * @returns The end of the month. | |
| */ | |
| this.endOfMonth = (date) => { | |
| return this.overrides?.endOfMonth | |
| ? this.overrides.endOfMonth(date) | |
| : endOfMonth(date); | |
| }; | |
| /** | |
| * Returns the end of the week for the given date. | |
| * | |
| * @param date The original date. | |
| * @returns The end of the week. | |
| */ | |
| this.endOfWeek = (date, options) => { | |
| return this.overrides?.endOfWeek | |
| ? this.overrides.endOfWeek(date, options) | |
| : endOfWeek(date, this.options); | |
| }; | |
| /** | |
| * Returns the end of the year for the given date. | |
| * | |
| * @param date The original date. | |
| * @returns The end of the year. | |
| */ | |
| this.endOfYear = (date) => { | |
| return this.overrides?.endOfYear | |
| ? this.overrides.endOfYear(date) | |
| : endOfYear(date); | |
| }; | |
| /** | |
| * Formats the given date using the specified format string. | |
| * | |
| * @param date The date to format. | |
| * @param formatStr The format string. | |
| * @returns The formatted date string. | |
| */ | |
| this.format = (date, formatStr, _options) => { | |
| const formatted = this.overrides?.format | |
| ? this.overrides.format(date, formatStr, this.options) | |
| : format(date, formatStr, this.options); | |
| if (this.options.numerals && this.options.numerals !== "latn") { | |
| return this.replaceDigits(formatted); | |
| } | |
| return formatted; | |
| }; | |
| /** | |
| * Returns the ISO week number for the given date. | |
| * | |
| * @param date The date to get the ISO week number for. | |
| * @returns The ISO week number. | |
| */ | |
| this.getISOWeek = (date) => { | |
| return this.overrides?.getISOWeek | |
| ? this.overrides.getISOWeek(date) | |
| : getISOWeek(date); | |
| }; | |
| /** | |
| * Returns the month of the given date. | |
| * | |
| * @param date The date to get the month for. | |
| * @returns The month. | |
| */ | |
| this.getMonth = (date, _options) => { | |
| return this.overrides?.getMonth | |
| ? this.overrides.getMonth(date, this.options) | |
| : getMonth(date, this.options); | |
| }; | |
| /** | |
| * Returns the year of the given date. | |
| * | |
| * @param date The date to get the year for. | |
| * @returns The year. | |
| */ | |
| this.getYear = (date, _options) => { | |
| return this.overrides?.getYear | |
| ? this.overrides.getYear(date, this.options) | |
| : getYear(date, this.options); | |
| }; | |
| /** | |
| * Returns the local week number for the given date. | |
| * | |
| * @param date The date to get the week number for. | |
| * @returns The week number. | |
| */ | |
| this.getWeek = (date, _options) => { | |
| return this.overrides?.getWeek | |
| ? this.overrides.getWeek(date, this.options) | |
| : getWeek(date, this.options); | |
| }; | |
| /** | |
| * Checks if the first date is after the second date. | |
| * | |
| * @param date The date to compare. | |
| * @param dateToCompare The date to compare with. | |
| * @returns True if the first date is after the second date. | |
| */ | |
| this.isAfter = (date, dateToCompare) => { | |
| return this.overrides?.isAfter | |
| ? this.overrides.isAfter(date, dateToCompare) | |
| : isAfter(date, dateToCompare); | |
| }; | |
| /** | |
| * Checks if the first date is before the second date. | |
| * | |
| * @param date The date to compare. | |
| * @param dateToCompare The date to compare with. | |
| * @returns True if the first date is before the second date. | |
| */ | |
| this.isBefore = (date, dateToCompare) => { | |
| return this.overrides?.isBefore | |
| ? this.overrides.isBefore(date, dateToCompare) | |
| : isBefore(date, dateToCompare); | |
| }; | |
| /** | |
| * Checks if the given value is a Date object. | |
| * | |
| * @param value The value to check. | |
| * @returns True if the value is a Date object. | |
| */ | |
| this.isDate = (value) => { | |
| return this.overrides?.isDate | |
| ? this.overrides.isDate(value) | |
| : isDate(value); | |
| }; | |
| /** | |
| * Checks if the given dates are on the same day. | |
| * | |
| * @param dateLeft The first date to compare. | |
| * @param dateRight The second date to compare. | |
| * @returns True if the dates are on the same day. | |
| */ | |
| this.isSameDay = (dateLeft, dateRight) => { | |
| return this.overrides?.isSameDay | |
| ? this.overrides.isSameDay(dateLeft, dateRight) | |
| : isSameDay(dateLeft, dateRight); | |
| }; | |
| /** | |
| * Checks if the given dates are in the same month. | |
| * | |
| * @param dateLeft The first date to compare. | |
| * @param dateRight The second date to compare. | |
| * @returns True if the dates are in the same month. | |
| */ | |
| this.isSameMonth = (dateLeft, dateRight) => { | |
| return this.overrides?.isSameMonth | |
| ? this.overrides.isSameMonth(dateLeft, dateRight) | |
| : isSameMonth(dateLeft, dateRight); | |
| }; | |
| /** | |
| * Checks if the given dates are in the same year. | |
| * | |
| * @param dateLeft The first date to compare. | |
| * @param dateRight The second date to compare. | |
| * @returns True if the dates are in the same year. | |
| */ | |
| this.isSameYear = (dateLeft, dateRight) => { | |
| return this.overrides?.isSameYear | |
| ? this.overrides.isSameYear(dateLeft, dateRight) | |
| : isSameYear(dateLeft, dateRight); | |
| }; | |
| /** | |
| * Returns the latest date in the given array of dates. | |
| * | |
| * @param dates The array of dates to compare. | |
| * @returns The latest date. | |
| */ | |
| this.max = (dates) => { | |
| return this.overrides?.max ? this.overrides.max(dates) : max(dates); | |
| }; | |
| /** | |
| * Returns the earliest date in the given array of dates. | |
| * | |
| * @param dates The array of dates to compare. | |
| * @returns The earliest date. | |
| */ | |
| this.min = (dates) => { | |
| return this.overrides?.min ? this.overrides.min(dates) : min(dates); | |
| }; | |
| /** | |
| * Sets the month of the given date. | |
| * | |
| * @param date The date to set the month on. | |
| * @param month The month to set (0-11). | |
| * @returns The new date with the month set. | |
| */ | |
| this.setMonth = (date, month) => { | |
| return this.overrides?.setMonth | |
| ? this.overrides.setMonth(date, month) | |
| : setMonth(date, month); | |
| }; | |
| /** | |
| * Sets the year of the given date. | |
| * | |
| * @param date The date to set the year on. | |
| * @param year The year to set. | |
| * @returns The new date with the year set. | |
| */ | |
| this.setYear = (date, year) => { | |
| return this.overrides?.setYear | |
| ? this.overrides.setYear(date, year) | |
| : setYear(date, year); | |
| }; | |
| /** | |
| * Returns the start of the broadcast week for the given date. | |
| * | |
| * @param date The original date. | |
| * @returns The start of the broadcast week. | |
| */ | |
| this.startOfBroadcastWeek = (date, _dateLib) => { | |
| return this.overrides?.startOfBroadcastWeek | |
| ? this.overrides.startOfBroadcastWeek(date, this) | |
| : startOfBroadcastWeek(date, this); | |
| }; | |
| /** | |
| * Returns the start of the day for the given date. | |
| * | |
| * @param date The original date. | |
| * @returns The start of the day. | |
| */ | |
| this.startOfDay = (date) => { | |
| return this.overrides?.startOfDay | |
| ? this.overrides.startOfDay(date) | |
| : startOfDay(date); | |
| }; | |
| /** | |
| * Returns the start of the ISO week for the given date. | |
| * | |
| * @param date The original date. | |
| * @returns The start of the ISO week. | |
| */ | |
| this.startOfISOWeek = (date) => { | |
| return this.overrides?.startOfISOWeek | |
| ? this.overrides.startOfISOWeek(date) | |
| : startOfISOWeek(date); | |
| }; | |
| /** | |
| * Returns the start of the month for the given date. | |
| * | |
| * @param date The original date. | |
| * @returns The start of the month. | |
| */ | |
| this.startOfMonth = (date) => { | |
| return this.overrides?.startOfMonth | |
| ? this.overrides.startOfMonth(date) | |
| : startOfMonth(date); | |
| }; | |
| /** | |
| * Returns the start of the week for the given date. | |
| * | |
| * @param date The original date. | |
| * @returns The start of the week. | |
| */ | |
| this.startOfWeek = (date, _options) => { | |
| return this.overrides?.startOfWeek | |
| ? this.overrides.startOfWeek(date, this.options) | |
| : startOfWeek(date, this.options); | |
| }; | |
| /** | |
| * Returns the start of the year for the given date. | |
| * | |
| * @param date The original date. | |
| * @returns The start of the year. | |
| */ | |
| this.startOfYear = (date) => { | |
| return this.overrides?.startOfYear | |
| ? this.overrides.startOfYear(date) | |
| : startOfYear(date); | |
| }; | |
| this.options = { locale: enUS, ...options }; | |
| this.overrides = overrides; | |
| } | |
| /** | |
| * Generates a mapping of Arabic digits (0-9) to the target numbering system | |
| * digits. | |
| * | |
| * @since 9.5.0 | |
| * @returns A record mapping Arabic digits to the target numerals. | |
| */ | |
| getDigitMap() { | |
| const { numerals = "latn" } = this.options; | |
| // Use Intl.NumberFormat to create a formatter with the specified numbering system | |
| const formatter = new Intl.NumberFormat("en-US", { | |
| numberingSystem: numerals, | |
| }); | |
| // Map Arabic digits (0-9) to the target numerals | |
| const digitMap = {}; | |
| for (let i = 0; i < 10; i++) { | |
| digitMap[i.toString()] = formatter.format(i); | |
| } | |
| return digitMap; | |
| } | |
| /** | |
| * Replaces Arabic digits in a string with the target numbering system digits. | |
| * | |
| * @since 9.5.0 | |
| * @param input The string containing Arabic digits. | |
| * @returns The string with digits replaced. | |
| */ | |
| replaceDigits(input) { | |
| const digitMap = this.getDigitMap(); | |
| return input.replace(/\d/g, (digit) => digitMap[digit] || digit); | |
| } | |
| /** | |
| * Formats a number using the configured numbering system. | |
| * | |
| * @since 9.5.0 | |
| * @param value The number to format. | |
| * @returns The formatted number as a string. | |
| */ | |
| formatNumber(value) { | |
| return this.replaceDigits(value.toString()); | |
| } | |
| /** | |
| * Returns the preferred ordering for month and year labels for the current | |
| * locale. | |
| */ | |
| getMonthYearOrder() { | |
| const code = this.options.locale?.code; | |
| if (!code) { | |
| return "month-first"; | |
| } | |
| return DateLib.yearFirstLocales.has(code) ? "year-first" : "month-first"; | |
| } | |
| /** | |
| * Formats the month/year pair respecting locale conventions. | |
| * | |
| * @since 9.11.0 | |
| */ | |
| formatMonthYear(date) { | |
| const { locale, timeZone, numerals } = this.options; | |
| const localeCode = locale?.code; | |
| if (localeCode && DateLib.yearFirstLocales.has(localeCode)) { | |
| try { | |
| const intl = new Intl.DateTimeFormat(localeCode, { | |
| month: "long", | |
| year: "numeric", | |
| timeZone, | |
| numberingSystem: numerals, | |
| }); | |
| const formatted = intl.format(date); | |
| return formatted; | |
| } | |
| catch { | |
| // Fallback to date-fns formatting below. | |
| } | |
| } | |
| const pattern = this.getMonthYearOrder() === "year-first" ? "y LLLL" : "LLLL y"; | |
| return this.format(date, pattern); | |
| } | |
| } | |
| DateLib.yearFirstLocales = new Set([ | |
| "eu", | |
| "hu", | |
| "ja", | |
| "ja-Hira", | |
| "ja-JP", | |
| "ko", | |
| "ko-KR", | |
| "lt", | |
| "lt-LT", | |
| "lv", | |
| "lv-LV", | |
| "mn", | |
| "mn-MN", | |
| "zh", | |
| "zh-CN", | |
| "zh-HK", | |
| "zh-TW", | |
| ]); | |
| /** The default locale (English). */ | |
| export { enUS as defaultLocale } from "../locale/en-US.js"; | |
| /** | |
| * The default date library with English locale. | |
| * | |
| * @since 9.2.0 | |
| */ | |
| export const defaultDateLib = new DateLib(); | |
| /** | |
| * @ignore | |
| * @deprecated Use `defaultDateLib`. | |
| */ | |
| export const dateLib = defaultDateLib; | |