date-fns-tz
Version:
Time zone support for date-fns v3 with the Intl API
127 lines (126 loc) • 5.25 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatters = void 0;
const index_js_1 = require("../../_lib/tzIntlTimeZoneName/index.js");
const index_js_2 = require("../../_lib/tzParseTimezone/index.js");
const MILLISECONDS_IN_MINUTE = 60 * 1000;
exports.formatters = {
// Timezone (ISO-8601. If offset is 0, output is always `'Z'`)
X: function (date, token, options) {
const timezoneOffset = getTimeZoneOffset(options.timeZone, date);
if (timezoneOffset === 0) {
return 'Z';
}
switch (token) {
// Hours and optional minutes
case 'X':
return formatTimezoneWithOptionalMinutes(timezoneOffset);
// Hours, minutes and optional seconds without `:` delimeter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `XX`
case 'XXXX':
case 'XX': // Hours and minutes without `:` delimeter
return formatTimezone(timezoneOffset);
// Hours, minutes and optional seconds with `:` delimeter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `XXX`
case 'XXXXX':
case 'XXX': // Hours and minutes with `:` delimeter
default:
return formatTimezone(timezoneOffset, ':');
}
},
// Timezone (ISO-8601. If offset is 0, output is `'+00:00'` or equivalent)
x: function (date, token, options) {
const timezoneOffset = getTimeZoneOffset(options.timeZone, date);
switch (token) {
// Hours and optional minutes
case 'x':
return formatTimezoneWithOptionalMinutes(timezoneOffset);
// Hours, minutes and optional seconds without `:` delimeter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `xx`
case 'xxxx':
case 'xx': // Hours and minutes without `:` delimeter
return formatTimezone(timezoneOffset);
// Hours, minutes and optional seconds with `:` delimeter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `xxx`
case 'xxxxx':
case 'xxx': // Hours and minutes with `:` delimeter
default:
return formatTimezone(timezoneOffset, ':');
}
},
// Timezone (GMT)
O: function (date, token, options) {
const timezoneOffset = getTimeZoneOffset(options.timeZone, date);
switch (token) {
// Short
case 'O':
case 'OO':
case 'OOO':
return 'GMT' + formatTimezoneShort(timezoneOffset, ':');
// Long
case 'OOOO':
default:
return 'GMT' + formatTimezone(timezoneOffset, ':');
}
},
// Timezone (specific non-location)
z: function (date, token, options) {
switch (token) {
// Short
case 'z':
case 'zz':
case 'zzz':
return (0, index_js_1.tzIntlTimeZoneName)('short', date, options);
// Long
case 'zzzz':
default:
return (0, index_js_1.tzIntlTimeZoneName)('long', date, options);
}
},
};
function getTimeZoneOffset(timeZone, originalDate) {
var _a;
const timeZoneOffset = timeZone
? (0, index_js_2.tzParseTimezone)(timeZone, originalDate, true) / MILLISECONDS_IN_MINUTE
: (_a = originalDate === null || originalDate === void 0 ? void 0 : originalDate.getTimezoneOffset()) !== null && _a !== void 0 ? _a : 0;
if (Number.isNaN(timeZoneOffset)) {
throw new RangeError('Invalid time zone specified: ' + timeZone);
}
return timeZoneOffset;
}
function addLeadingZeros(number, targetLength) {
const sign = number < 0 ? '-' : '';
let output = Math.abs(number).toString();
while (output.length < targetLength) {
output = '0' + output;
}
return sign + output;
}
function formatTimezone(offset, delimiter = '') {
const sign = offset > 0 ? '-' : '+';
const absOffset = Math.abs(offset);
const hours = addLeadingZeros(Math.floor(absOffset / 60), 2);
const minutes = addLeadingZeros(Math.floor(absOffset % 60), 2);
return sign + hours + delimiter + minutes;
}
function formatTimezoneWithOptionalMinutes(offset, delimiter) {
if (offset % 60 === 0) {
const sign = offset > 0 ? '-' : '+';
return sign + addLeadingZeros(Math.abs(offset) / 60, 2);
}
return formatTimezone(offset, delimiter);
}
function formatTimezoneShort(offset, delimiter = '') {
const sign = offset > 0 ? '-' : '+';
const absOffset = Math.abs(offset);
const hours = Math.floor(absOffset / 60);
const minutes = absOffset % 60;
if (minutes === 0) {
return sign + String(hours);
}
return sign + String(hours) + delimiter + addLeadingZeros(minutes, 2);
}