UNPKG

react-day-picker

Version:

Customizable Date Picker for React

160 lines (159 loc) 6.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createNoonOverrides = createNoonOverrides; const tz_1 = require("@date-fns/tz"); const date_fns_1 = require("date-fns"); /** * Creates `dateLib` overrides that keep all calendar math at noon in the target * time zone. This avoids second-level offset changes (e.g., historical zones * with +03:41:12) from pushing dates backward across midnight. */ function createNoonOverrides(timeZone, options = {}) { const { weekStartsOn, locale } = options; const fallbackWeekStartsOn = (weekStartsOn ?? locale?.options?.weekStartsOn ?? 0); // Keep all internal math anchored at noon in the target zone to avoid // historical second-level offsets from crossing midnight. const toNoonTZDate = (date) => { const normalizedDate = typeof date === "number" || typeof date === "string" ? new Date(date) : date; return new tz_1.TZDate(normalizedDate.getFullYear(), normalizedDate.getMonth(), normalizedDate.getDate(), 12, 0, 0, timeZone); }; // Convert a value into a host `Date` that represents the same calendar day // as the target-zone noon. This is useful for helpers (e.g., date-fns week // utilities) that expect local `Date` instances rather than `TZDate`s. const toCalendarDate = (date) => { const zoned = toNoonTZDate(date); return new Date(zoned.getFullYear(), zoned.getMonth(), zoned.getDate(), 0, 0, 0, 0); }; return { today: () => { return toNoonTZDate(tz_1.TZDate.tz(timeZone)); }, newDate: (year, monthIndex, date) => { return new tz_1.TZDate(year, monthIndex, date, 12, 0, 0, timeZone); }, startOfDay: (date) => { return toNoonTZDate(date); }, startOfWeek: (date, options) => { const base = toNoonTZDate(date); const weekStartsOnValue = (options?.weekStartsOn ?? fallbackWeekStartsOn); const diff = (base.getDay() - weekStartsOnValue + 7) % 7; base.setDate(base.getDate() - diff); return base; }, startOfISOWeek: (date) => { const base = toNoonTZDate(date); const diff = (base.getDay() - 1 + 7) % 7; base.setDate(base.getDate() - diff); return base; }, startOfMonth: (date) => { const base = toNoonTZDate(date); base.setDate(1); return base; }, startOfYear: (date) => { const base = toNoonTZDate(date); base.setMonth(0, 1); return base; }, endOfWeek: (date, options) => { const base = toNoonTZDate(date); const weekStartsOnValue = (options?.weekStartsOn ?? fallbackWeekStartsOn); const endDow = (weekStartsOnValue + 6) % 7; const diff = (endDow - base.getDay() + 7) % 7; base.setDate(base.getDate() + diff); return base; }, endOfISOWeek: (date) => { const base = toNoonTZDate(date); const diff = (7 - base.getDay()) % 7; base.setDate(base.getDate() + diff); return base; }, endOfMonth: (date) => { const base = toNoonTZDate(date); base.setMonth(base.getMonth() + 1, 0); return base; }, endOfYear: (date) => { const base = toNoonTZDate(date); base.setMonth(11, 31); return base; }, eachMonthOfInterval: (interval) => { const start = toNoonTZDate(interval.start); const end = toNoonTZDate(interval.end); const result = []; const cursor = new tz_1.TZDate(start.getFullYear(), start.getMonth(), 1, 12, 0, 0, timeZone); const endKey = end.getFullYear() * 12 + end.getMonth(); while (cursor.getFullYear() * 12 + cursor.getMonth() <= endKey) { result.push(new tz_1.TZDate(cursor, timeZone)); cursor.setMonth(cursor.getMonth() + 1, 1); } return result; }, // Normalize to noon once before arithmetic (avoid DST/midnight edge cases), // mutate the same TZDate, and return it. addDays: (date, amount) => { const base = toNoonTZDate(date); base.setDate(base.getDate() + amount); return base; }, addWeeks: (date, amount) => { const base = toNoonTZDate(date); base.setDate(base.getDate() + amount * 7); return base; }, addMonths: (date, amount) => { const base = toNoonTZDate(date); base.setMonth(base.getMonth() + amount); return base; }, addYears: (date, amount) => { const base = toNoonTZDate(date); base.setFullYear(base.getFullYear() + amount); return base; }, eachYearOfInterval: (interval) => { const start = toNoonTZDate(interval.start); const end = toNoonTZDate(interval.end); const years = []; const cursor = new tz_1.TZDate(start.getFullYear(), 0, 1, 12, 0, 0, timeZone); while (cursor.getFullYear() <= end.getFullYear()) { years.push(new tz_1.TZDate(cursor, timeZone)); cursor.setFullYear(cursor.getFullYear() + 1, 0, 1); } return years; }, getWeek: (date, options) => { const base = toCalendarDate(date); return (0, date_fns_1.getWeek)(base, { weekStartsOn: options?.weekStartsOn ?? fallbackWeekStartsOn, firstWeekContainsDate: options?.firstWeekContainsDate ?? locale?.options?.firstWeekContainsDate ?? 1, }); }, getISOWeek: (date) => { const base = toCalendarDate(date); return (0, date_fns_1.getISOWeek)(base); }, differenceInCalendarDays: (dateLeft, dateRight) => { const left = toCalendarDate(dateLeft); const right = toCalendarDate(dateRight); return (0, date_fns_1.differenceInCalendarDays)(left, right); }, differenceInCalendarMonths: (dateLeft, dateRight) => { const left = toCalendarDate(dateLeft); const right = toCalendarDate(dateRight); return (0, date_fns_1.differenceInCalendarMonths)(left, right); }, }; }