forked from sagnik/Project_Velocity
160 lines
6.5 KiB
JavaScript
160 lines
6.5 KiB
JavaScript
"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);
|
|
},
|
|
};
|
|
}
|