date-fns-tz
Version:
Time zone support for date-fns v3 with the Intl API
98 lines (97 loc) • 3.38 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tzTokenizeDate = void 0;
/**
* Returns the [year, month, day, hour, minute, seconds] tokens of the provided
* `date` as it will be rendered in the `timeZone`.
*/
function tzTokenizeDate(date, timeZone) {
const dtf = getDateTimeFormat(timeZone);
return 'formatToParts' in dtf ? partsOffset(dtf, date) : hackyOffset(dtf, date);
}
exports.tzTokenizeDate = tzTokenizeDate;
const typeToPos = {
year: 0,
month: 1,
day: 2,
hour: 3,
minute: 4,
second: 5,
};
function partsOffset(dtf, date) {
try {
const formatted = dtf.formatToParts(date);
const filled = [];
for (let i = 0; i < formatted.length; i++) {
const pos = typeToPos[formatted[i].type];
if (pos !== undefined) {
filled[pos] = parseInt(formatted[i].value, 10);
}
}
return filled;
}
catch (error) {
if (error instanceof RangeError) {
return [NaN];
}
throw error;
}
}
function hackyOffset(dtf, date) {
const formatted = dtf.format(date);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const parsed = /(\d+)\/(\d+)\/(\d+),? (\d+):(\d+):(\d+)/.exec(formatted);
// const [, fMonth, fDay, fYear, fHour, fMinute, fSecond] = parsed
// return [fYear, fMonth, fDay, fHour, fMinute, fSecond]
return [
parseInt(parsed[3], 10),
parseInt(parsed[1], 10),
parseInt(parsed[2], 10),
parseInt(parsed[4], 10),
parseInt(parsed[5], 10),
parseInt(parsed[6], 10),
];
}
// Get a cached Intl.DateTimeFormat instance for the IANA `timeZone`. This can be used
// to get deterministic local date/time output according to the `en-US` locale which
// can be used to extract local time parts as necessary.
const dtfCache = {};
function getDateTimeFormat(timeZone) {
if (!dtfCache[timeZone]) {
// New browsers use `hourCycle`, IE and Chrome <73 does not support it and uses `hour12`
const testDateFormatted = new Intl.DateTimeFormat('en-US', {
hourCycle: 'h23',
timeZone: 'America/New_York',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
}).format(new Date('2014-06-25T04:00:00.123Z'));
const hourCycleSupported = testDateFormatted === '06/25/2014, 00:00:00' ||
testDateFormatted === '06/25/2014 00:00:00';
dtfCache[timeZone] = hourCycleSupported
? new Intl.DateTimeFormat('en-US', {
hourCycle: 'h23',
timeZone: timeZone,
year: 'numeric',
month: 'numeric',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
})
: new Intl.DateTimeFormat('en-US', {
hour12: false,
timeZone: timeZone,
year: 'numeric',
month: 'numeric',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
});
}
return dtfCache[timeZone];
}