datetime_global
Version:
my Datetime untility, it mixes the Advanced capabilities of Temporal polyfill with the simplicity of Date
1,173 lines (1,172 loc) • 74.1 kB
JavaScript
import { Temporal } from 'temporal-polyfill';
import { ZDTDuration } from "./ZDTDuration.js";
/**
* this class `Datetime_global` should behave exactly like `Date` if a name matches that on `Date`.
* except `toJSON`. until now. that was the design goal all along. to have Date with `Temporal`'s precision
*/
// npm: https://www.npmjs.com/package/datetime_global
// github: https://github.com/DNSCond/Datetime-local
"use strict"; // [^\x00-\x7F]
const useOldJSON = Symbol('useOldJSON');
const [writable, enumerable, configurable] = [true, true, true];
/**
* Constructs a Datetime_global instance or returns a string representation.
* @param from - Input to initialize the date-time. Supports:
* - Temporal.ZonedDateTime: Used directly.
* - Temporal.Instant: Converted from epoch nanoseconds.
* - Date | Datetime_global: Converted from epoch milliseconds.
* - bigint: Nanoseconds since epoch.
* - number: Milliseconds since epoch.
* - string: Parsed using `Date.parse` (EcmaScript format or browser-dependent formats).
* - undefined: Uses current time (Datetime_global.now()).
* @param timezoneId - A Temporal.TimeZoneLike or IANA timezone string (e.g., "UTC"). Defaults to local timezone (Temporal.Now.timeZoneId()).
* @returns A Datetime_global instance if called with `new`, or a string representation if called as a function.
* @throws TypeError if timezoneId is invalid or if BigInt conversion fails.
* @throws RangeError if the input string cannot be parsed or results in an invalid date.
* @example
* // Current time in local timezone (assuming its America/New_York)
* const now = new Datetime_global();
* console.log(now.toString()); // e.g., "Fri Apr 18 2025 12:00:00 UTC-0400 (America/New_York)"
*
* // From Date in UTC
* const fromDate = new Datetime_global(new Date("2025-04-18T00:00:00Z"), "UTC");
* console.log(fromDate.toISOString()); // "2025-04-18T00:00:00.000Z"
*
* // From nanoseconds (bigint)
* const fromBigInt = new Datetime_global(1745193600000000000n, "UTC"); // April 18, 2025
* console.log(fromBigInt.toISOString()); // "2025-04-18T00:00:00.000Z"
*
* // From ISO string
* const fromString = new Datetime_global("2025-04-18T00:00:00Z", "Asia/Tokyo");
* console.log(fromString.toString()); // e.g., "Fri Apr 18 2025 09:00:00 UTC+0900 (Asia/Tokyo)"
*
* // As a function (returns string)
* const asString = Datetime_global(new Date("2025-04-18T00:00:00Z"), "UTC");
* console.log(asString); // "Fri Apr 18 2025 00:00:00 UTC+0000 (UTC)"
* @constructor
* @function
*/
export const Datetime_global = function (from = undefined, timezoneId = Temporal.Now.timeZoneId()) {
let timestamp, isBigInt = false;
if (arguments.length === 0 || from === undefined) {
from = Datetime_global.now();
}
if (from instanceof Temporal.ZonedDateTime) {
timestamp = 0n;
}
else if (from instanceof Temporal.Instant) {
timestamp = BigInt(from.epochNanoseconds);
isBigInt = true;
}
else if (from instanceof Datetime_global) {
timestamp = from.time.epochNanoseconds;
isBigInt = true;
}
else if (typeof from === 'bigint') {
timestamp = from;
isBigInt = true;
}
else if (typeof from === 'string') {
timestamp = Date.parse(from);
}
else {
timestamp = Math.trunc(from);
}
if (typeof timestamp === 'number' && new.target === undefined) {
if (!Number.isSafeInteger(timestamp)) {
return "Invalid Date";
}
}
const value = from instanceof Temporal.ZonedDateTime ? from : new Temporal.ZonedDateTime(BigInt(timestamp) * (isBigInt ? 1n : 1000000n), timezoneId);
const self = new.target ? this : Object.create(Datetime_global.prototype);
Object.defineProperties(self, {
time: { value, writable, enumerable, configurable, },
year: {
get() {
return this.getFullYear();
}, enumerable, configurable,
}, month: {
get() {
return this.time.month;
}, enumerable, configurable,
}, day: {
get() {
return this.getDate();
}, enumerable, configurable,
}, dayOfWeek: {
get() {
return this.time.dayOfWeek;
}, enumerable, configurable,
}, hour: {
get() {
return this.getHours();
}, enumerable, configurable,
}, minute: {
get() {
return this.getMinutes();
}, enumerable, configurable,
}, second: {
get() {
return this.getSeconds();
}, enumerable, configurable,
}, millisecond: {
get() {
return this.time.millisecond;
}, enumerable, configurable,
}, microsecond: {
get() {
return this.time.microsecond;
}, enumerable, configurable,
}, nanosecond: {
get() {
return this.time.nanosecond;
}, enumerable, configurable,
}, epochMilliseconds: {
get() {
return this.time.epochMilliseconds;
}, enumerable, configurable,
}, epochNanoseconds: {
get() {
return this.time.epochNanoseconds;
}, set(value) {
this.time = new Temporal.ZonedDateTime(BigInt(value), this.timezoneId);
}, enumerable, configurable,
},
});
if (!new.target)
return self.toString();
else
self.useOldJSON = true;
};
Object.defineProperties(Datetime_global.prototype, {
minutesAfterMidnight: {
get() {
const { time } = this;
return time.startOfDay().until(time, {
smallestUnit: 'minutes',
largestUnit: 'minutes',
}).minutes;
}, set(value) {
this.setHours(0, Math.trunc(value));
}, enumerable, configurable,
}, timezoneId: {
get() {
return this.time.timeZoneId;
}, set(value) {
this.time = this.toTimezone(value).toTemporalZonedDateTime();
}, enumerable, configurable,
}, date: {
get() {
return this.toDate();
}, set(value) {
if (value instanceof Date) {
const instant = Temporal.Instant.fromEpochMilliseconds(value);
this.time = new Temporal.ZonedDateTime(instant.epochNanoseconds, this.getTimezoneId());
}
else
throw new TypeError('date must be set using a Date.');
}, enumerable, configurable,
}, useOldJSON: {
get() {
return this[useOldJSON];
}, set(value) {
if (value === true || value === false) {
this[useOldJSON] = value;
}
else {
throw new TypeError('useOldJSON must be set using an explicit boolean');
}
}, enumerable, configurable,
},
});
Datetime_global.prototype.setOldJSON = function (useOldJSON) {
this.useOldJSON = useOldJSON;
return this;
};
Datetime_global.compare = function (zonedDatetime1, zonedDatetime2) {
zonedDatetime1 = new Datetime_global(zonedDatetime1, 'UTC');
zonedDatetime2 = new Datetime_global(zonedDatetime2, 'UTC');
const nano1 = zonedDatetime1.getTimestamp(), nano2 = zonedDatetime2.getTimestamp();
if (nano1 > nano2) {
return +1;
}
else if (nano1 < nano2) {
return -1;
}
else {
return +0;
}
};
/**
* Creates a UTC timestamp from date-time components, returning nanoseconds since the epoch.
* @param year - The year (0-99 maps to 1900-1999; otherwise used as-is). if it's a string the `Date.parse` is used
* @param month - The month (0-11; default 0, January).
* @param date - The day of the month (1-31; default 1).
* @param hour - The hour (0-23; default 0).
* @param minute - The minute (0-59; default 0).
* @param second - The second (0-59; default 0).
* @param millisecond - The millisecond (0-999; default 0).
* @param nanosecond - The nanosecond (default 0).
* @returns The nanoseconds since the epoch (January 1, 1970, 00:00:00 UTC).
* @throws RangeError if the components form an invalid date.
* @example
* // April 18, 2025, 00:00:00 UTC
* console.log(Datetime_global.fromComponentsUTC(2025, 3, 18));
* // 1745193600000000000n
*
* // With nanoseconds
* console.log(Datetime_global.fromComponentsUTC(2025, 3, 18, 0, 0, 0, 0, 500));
* // 1745193600000000500n
*/
Datetime_global.fromComponentsUTC = function (year, month = 0, date = 1, hour = 0, minute = 0, second = 0, millisecond = 0, nanosecond = 0n) {
const date_time = new Date;
if (arguments.length === 1) {
if (typeof year === 'string') {
year = Date.parse(year);
}
date_time.setTime(year);
}
else if (arguments.length > 1) {
date_time.setTime(Date.UTC(year, month, date, hour, minute, second, millisecond));
}
return (BigInt(date_time.getTime()) * 1000000n) + BigInt(nanosecond);
};
/**
* Parses a string into a Temporal.ZonedDateTime using strict ISO 8601 parsing.
* @param string - An ISO 8601 string (e.g., "2025-04-18T00:00:00Z") or object with date-time fields.
* @returns A Temporal.ZonedDateTime instance.
* @throws RangeError if the string is invalid or cannot be parsed.
* @example
* const zdt = Datetime_global.parse_strict("2025-04-18T00:00:00Z");
* console.log(zdt.toString()); // "2025-04-18T00:00:00+00:00[UTC]"
*/
Datetime_global.parse_strict = function (string) {
return Temporal.ZonedDateTime.from(string);
};
/**
* Returns the current timestamp as nanoseconds since the epoch (January 1, 1970, 00:00:00 UTC).
* @returns The nanoseconds since the epoch.
* @example
* console.log(Datetime_global.now()); // e.g., 1745193600000000000n
*/
Datetime_global.now = function () {
return Temporal.Now.instant().epochNanoseconds;
};
/**
* Returns the current timestamp as nanoseconds since the epoch (January 1, 1970, 00:00:00 UTC).
* @returns The nanoseconds since the epoch.
* @example
* console.log(Datetime_global.now()); // e.g., 1745193600000000000n
*/
Datetime_global.nowInTimezone = function (timezone) {
if (timezone)
return new Datetime_global(Datetime_global.now(), timezone);
return new Datetime_global;
};
/**
* Returns the current timestamp in milliseconds since the epoch, with sub-second components (milliseconds, microseconds, nanoseconds) set to 0.
* @returns The milliseconds since the epoch.
* @example
* console.log(Datetime_global.zeroms()); // e.g., 1745193600000
*/
Datetime_global.zeroms = function () {
return (new Date).setMilliseconds(0);
};
/**
* Returns the current timestamp in nanoseconds since the epoch, with sub-second components (milliseconds, microseconds, nanoseconds) set to 0.
* @returns The nanoseconds since the epoch.
* @example
* console.log(Datetime_global.zerons()); // e.g., 1745193600000000000n
*/
Datetime_global.zerons = function () {
return BigInt(Datetime_global.zeroms()) * 1000000n;
};
/**
* Parses a date string into milliseconds since the epoch, using `Date.parse`.
* @param dateString - The date string to parse (e.g., "2025-04-18", "2025-04-18T00:00:00Z").
* @returns The milliseconds since the epoch, or NaN if invalid.
* @example
* console.log(Datetime_global.parse("2025-04-18T00:00:00Z")); // 1745193600000
*/
Datetime_global.parse = Date.parse;
Datetime_global.prototype[Symbol.toStringTag] = 'Datetime_global';
Datetime_global[Symbol.toStringTag] = 'Datetime_global_constructor';
/**
* converts this Datetime_global to Date
* @returns {Date} the Date with millisecond precision. sub millisecond precision is lost
*/
Datetime_global.prototype.toDate = function () {
return new Date(this.time.epochMilliseconds);
};
/**
* Creates a new Datetime_global in the specified timezone, preserving the instant in time.
* @param timezoneId - A Temporal.TimeZoneLike or IANA timezone string (e.g., "UTC", "America/New_York").
* @returns A new Datetime_global instance.
* @throws TypeError if timezoneId is invalid.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.toTimezone("Asia/Tokyo").toString());
* // "Fri Apr 18 2025 09:00:00 UTC+0900 (Asia/Tokyo)"
*/
Datetime_global.prototype.toTimezone = Datetime_global.prototype.withTimezone = function (timezoneId) {
return new Datetime_global(this.time.epochNanoseconds, timezoneId);
};
/**
* Retrieves the timezone identifier for this Datetime_global instance.
*
* @returns {string} The timezone identifier (e.g., "America/New_York") associated with the Temporal.ZonedDateTime instance.
*/
Datetime_global.prototype.getTimezoneId = function () {
return this.time.timeZoneId;
};
/**
* Returns the timestamp in milliseconds since the epoch (January 1, 1970, 00:00:00 UTC).
* @returns The milliseconds since the epoch.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.valueOf()); // 1745193600000
*/
Datetime_global.prototype.valueOf = function () {
return this.time.epochMilliseconds;
};
/**
*
* Returns the timestamp in milliseconds since the epoch (January 1, 1970, 00:00:00 UTC).
* @returns The milliseconds since the epoch.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.valueOf()); // 1745193600000
* @alias valueOf returning milliseconds since the epoch.
*/
Datetime_global.prototype.getTime = function () {
return this.valueOf();
};
/**
* Sets the timestamp, modifying the instance in place. Use the `Datetime_global` constructor instead.
* @param timestamp - Nanoseconds (bigint) or milliseconds (number) since the epoch.
* @returns The new timestamp in milliseconds since the epoch.
* @example
* const dt = new Datetime_global();
* dt.setTime(1745193600000);
* console.log(dt.toISOString()); // "2025-04-18T00:00:00.000Z"
*/
Datetime_global.prototype.setTime = function (timestamp) {
this.time = new Temporal.ZonedDateTime(BigInt(timestamp) * (((typeof timestamp) === 'bigint') ? 1n : 1000000n), this.time.timeZoneId);
return this.time.epochMilliseconds;
};
/**
* Returns a string representation of the date-time, including timezone offset and ID.
* Format (php): "D M d Y H:i:s \U\T\CO (e)" (e.g., "Fri Apr 18 2025 00:00:00 UTC+0000 (UTC)").
* @returns The formatted string.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.toString()); // "Fri Apr 18 2025 00:00:00 UTC+0000 (UTC)"
*/
Datetime_global.prototype.toString = function () {
const self = this, pad = (n, z = 2) => padNumber(n, z).replace(/^\+/, ''), fullYear = pad(self.time.withCalendar('iso8601').year, 4);
const offset = Datetime_global.getUTCOffset(self.getTimezoneOffset()), string = `${self.getDayName()} ${self.getMonthName()} ${pad(self.getDate())}`, time = `${pad(self.getHours())}:${pad(self.getMinutes())}:${pad(self.getSeconds())}`;
return `${string} ${fullYear} ${time} ${offset} (${self.time.timeZoneId})`;
};
/**
* Returns an HTML <time> element with the date-time in the browser's local timezone.
* The datetime attribute is in ISO 8601 format (UTC).
* @returns The HTML string (e.g., "<time datetime='2025-04-18T00:00:00.000Z'>Fri Apr 18 2025 00:00:00 UTC</time>").
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.toHTML()); // Depends on local timezone
*/
Datetime_global.prototype.toHTML = function () {
const date = new Date(this.time.epochMilliseconds);
return `<time datetime="${date.toISOString()}">${date}</time>`;
};
export function htmlencode(string) {
return String(string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
}
Datetime_global.prototype.toHTMLFormatted = function (dtg, format) {
return `<time datetime="${dtg.toISOString()}">${htmlencode(dtg.format(format))}</time>`;
};
/*
function htmlencode(string) {
return String(string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
}
const toHTMLFormatted = function(dtg, format) {
return `<time datetime="${dtg.toISOString()}">${htmlencode(dtg.format(format))}</time>`;
};
*/
/**
* Returns an HTML `<time>` element string representing the current datetime in GMT (UTC) format.
*
* The `datetime` attribute is set using the ISO 8601 string (`Date.prototype.toISOString()`),
* and the inner text of the element is the UTC string (`Date.prototype.toUTCString()`).
*
* This is useful for embedding machine-readable and human-readable timestamps in HTML,
* ensuring proper formatting and time zone clarity.
*
* @this {Datetime_global} The `Datetime_global` instance containing the time value.
* @returns {string} A string containing the `<time>` HTML element with GMT time.
*/
Datetime_global.prototype.toHTML_GMT = function () {
const date = new Date(this.time.epochMilliseconds);
return `<time datetime="${date.toISOString()}">${date.toUTCString()}</time>`;
};
Datetime_global.prototype.toHTML_UTC = function () {
return `<time datetime="${this.toISOString()}">${this.toUTCString()}</time>`;
};
Datetime_global.prototype.toHTMLHistoryString = function () {
const options = { smallestUnit: 'seconds', largestUnit: 'years' }, historyString = this.until(new Date, options).toHumanString(2);
return `<time datetime="${this.toISOString()}">${historyString}</time>`;
};
/**
* Returns an HTML <time> element with the date-time formatted in the instance's timezone.
* The datetime attribute is in ISO 8601 format (UTC).
* @returns The HTML string.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.toHTMLString());
* // "<time datetime='2025-04-18T00:00:00.000Z'>Fri Apr 18 2025 00:00:00 UTC+0000 (UTC)</time>"
*/
Datetime_global.prototype.toHTMLString = function () {
const date = new Date(this.time.epochMilliseconds);
return `<time datetime="${date.toISOString()}">${this.toString()}</time>`;
};
/**
* Returns the day of the week (0 = Sunday, 1 = Monday, ..., 6 = Saturday).
*
* will convert to the iso8601 calendar
* @returns The day of the week (0-6).
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC"); // Friday
* console.log(dt.getDay()); // 5
*/
Datetime_global.prototype.getDay = function () {
const time = this.time.withCalendar('iso8601');
return time.dayOfWeek % time.daysInWeek;
};
/**
* returns the true day of week arcording to the specified calendar
*/
Datetime_global.prototype.getDayOfWeek = function () {
return this.time.dayOfWeek;
};
/**
* Returns the year minus 1900 (e.g., 2025 -> 125) only iso8601 calendar.
* @returns The year minus 1900.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.getYear()); // 125
*/
Datetime_global.prototype.getYear = function () {
return this.time.withCalendar('iso8601').year - 1900;
};
/**
* Returns the full four-digit year (e.g., 2025).
* @returns The year.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.getFullYear()); // 2025
*/
Datetime_global.prototype.getFullYear = function () {
return this.time.year;
};
/**
* Returns the month (0 = January, 1 = February, ..., 11 = December).
* @returns The month (0-11).
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.getMonth()); // 3
*/
Datetime_global.prototype.getMonth = function () {
return this.time.month - 1;
};
/**
* Returns the day of the month (1-31).
* @returns The day of the month.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.getDate()); // 18
*/
Datetime_global.prototype.getDate = function () {
return this.time.day;
};
/**
* Returns the hour (0-23).
* @returns The hour.
* @example
* const dt = new Datetime_global("2025-04-18T15:00:00Z", "UTC");
* console.log(dt.getHours()); // 15
*/
Datetime_global.prototype.getHours = function () {
return this.time.hour;
};
/**
* Returns the minute (0-59).
* @returns The minute.
* @example
* const dt = new Datetime_global("2025-04-18T15:30:00Z", "UTC");
* console.log(dt.getMinutes()); // 30
*/
Datetime_global.prototype.getMinutes = function () {
return this.time.minute;
};
/**
* Returns the second (0-59).
* @returns The second.
* @example
* const dt = new Datetime_global("2025-04-18T15:30:45Z", "UTC");
* console.log(dt.getSeconds()); // 45
*/
Datetime_global.prototype.getSeconds = function () {
return this.time.second;
};
/**
* Returns the millisecond (0-999).
* @returns The millisecond.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00.123Z", "UTC");
* console.log(dt.getMilliseconds()); // 123
*/
Datetime_global.prototype.getMilliseconds = function () {
return this.time.millisecond;
};
// builtin-proxy-UTC
/**
* Returns the day of the week (0 = Sunday, 1 = Monday, ..., 6 = Saturday) in UTC.
* @returns The day of the week (0-6).
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC"); // Friday
* console.log(dt.getUTCDay()); // 5
*/
Datetime_global.prototype.getUTCDay = function () {
const date = new Date(this.time.epochMilliseconds);
return date.getUTCDay();
};
/**
* Returns the year minus 1900 (e.g., 2025 -> 125) in UTC.
*
* will convert to Date's calendar
* @returns The year minus 1900. in UTC
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.getYear()); // 125
*/
Datetime_global.prototype.getUTCYear = function () {
return this.getUTCFullYear() - 1900;
};
/**
* Returns the year in UTC.
*
* will convert to Date's calendar
* @returns The year minus in UTC
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.getUTCFullYear()); // 2025
*/
Datetime_global.prototype.getUTCFullYear = function () {
return this.toDate().getUTCFullYear();
};
/**
* Returns the month (0 = January, 1 = February, ..., 11 = December) in utc.
*
* will convert to Date's calendar
* @returns The month (0-11) in utc.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.getMonth()); // 3
*/
Datetime_global.prototype.getUTCMonth = function () {
const date = new Date(this.time.epochMilliseconds);
return date.getUTCMonth();
};
/**
* Returns the day of the month (1-31) in utc.
*
* will convert to Date's calendar
* @returns The day of the month in utc.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.getDate()); // 18
*/
Datetime_global.prototype.getUTCDate = function () {
const date = new Date(this.time.epochMilliseconds);
return date.getUTCDate();
};
/**
* Returns the hour (0-23) in utc.
*
* will convert to Date's calendar
* @returns The hour in utc.
* @example
* const dt = new Datetime_global("2025-04-18T15:00:00Z", "UTC");
* console.log(dt.getHours()); // 15
*/
Datetime_global.prototype.getUTCHours = function () {
return (new Date(this.time.epochMilliseconds)).getUTCHours();
};
/**
* Returns the minute (0-59) in utc.
*
* will convert to Date's calendar
* @returns The minute in utc.
* @example
* const dt = new Datetime_global("2025-04-18T15:30:00Z", "UTC");
* console.log(dt.getMinutes()); // 30
*/
Datetime_global.prototype.getUTCMinutes = function () {
const date = new Date(this.time.epochMilliseconds);
return date.getUTCMinutes();
};
/**
* Returns the second (0-59) in utc.
*
* will convert to Date's calendar
* @returns The second in utc.
* @example
* const dt = new Datetime_global("2025-04-18T15:30:45Z", "UTC");
* console.log(dt.getSeconds()); // 45
*/
Datetime_global.prototype.getUTCSeconds = function () {
const date = new Date(this.time.epochMilliseconds);
return date.getUTCSeconds();
};
/**
* Returns the millisecond (0-999) in utc.
*
* will convert to Date's calendar
* @returns The millisecond in utc.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00.123Z", "UTC");
* console.log(dt.getMilliseconds()); // 123
*/
Datetime_global.prototype.getUTCMilliseconds = function () {
const date = new Date(this.time.epochMilliseconds);
return date.getUTCMilliseconds();
};
/**
* Returns the timezone offset in minutes (positive for west of UTC, negative for east).
* @returns The offset in minutes.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "America/New_York");
* console.log(dt.getTimezoneOffset()); // 240 (4 hours west)
*/
Datetime_global.prototype.getTimezoneOffset = function () {
return -Math.trunc((Number(this.time.offsetNanoseconds) / 1e9) / 60);
};
/**
* Returns the date-time as an ISO 8601 string in UTC (e.g., "2025-04-18T12:34:56.789Z").
* Matches Date.prototype.toISOString, with millisecond precision.
* @returns A string in ISO 8601 format.
*/
Datetime_global.prototype.toISOString = function () {
return this.toDate().toISOString();
};
/**
* Returns the date-time as an ISO 8601 string with timezone (e.g., "2025-04-18T00:00:00+00:00[UTC]").
* @returns The ISO 8601 string.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.toJSON()); // "2025-04-18T00:00:00+00:00[UTC]"
*/
Datetime_global.prototype.toJSON = function () {
if (this[useOldJSON] === true)
return this.toDate().toJSON();
return this.time.toJSON();
};
/**
* Sets the year, optionally month and day, modifying the instance in place.
* Handles overflow/underflow by rolling over to adjacent months/years.
* @param fullYear - The year (e.g., 2025).
* @param month - The month (0-11; optional, defaults to current month).
* @param date - The day of the month (1-31; optional, defaults to current day).
* @returns The new timestamp in milliseconds since the epoch.
* @throws Error if excessive overflow causes recursion limit to be reached.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* dt.setFullYear(2026);
* console.log(dt.toISOString()); // "2026-04-18T00:00:00.000Z"
*/
Datetime_global.prototype.setFullYear = function (fullYear, month, date) {
date = arguments.length > 1 ? date : this.time.day;
month = arguments.length > 2 ? month : this.time.month;
const year = fullYear, try_date = {
year: toNumber(year), day: toNumber(date), month: toNumber(month) + 1,
}, self_time = overflowDatetime_global(this, try_date);
return (this.time = self_time).epochMilliseconds;
};
function toNumber(mixed) {
return Number(BigInt(Number(mixed)));
}
/**
* Sets the month, optionally day, modifying the instance in place.
* Handles overflow/underflow by rolling over to adjacent months/years.
* @param month - The month (0-11).
* @param date - The day of the month (1-31; optional, defaults to current day).
* @returns The new timestamp in milliseconds since the epoch.
* @throws Error if excessive overflow causes recursion limit to be reached.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* dt.setMonth(5); // June
* console.log(dt.toISOString()); // "2025-06-18T00:00:00.000Z"
*/
Datetime_global.prototype.setMonth = function (month, date) {
date = arguments.length > 1 ? date : this.getDate();
return this.setFullYear(this.getFullYear(), month, date);
};
/**
* Sets the day of the month, modifying the instance in place.
* Handles overflow/underflow by rolling over to adjacent months.
* @param date - The day of the month (1-31).
* @returns The new timestamp in milliseconds since the epoch.
* @throws Error if excessive overflow causes recursion limit to be reached.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* dt.setDate(19);
* console.log(dt.toISOString()); // "2025-04-19T00:00:00.000Z"
*/
Datetime_global.prototype.setDate = function (date) {
return this.setFullYear(this.getFullYear(), this.getMonth(), date);
};
/**
* Sets the hours, minutes, seconds, and milliseconds, modifying the object in place.
* Handles overflow/underflow by rolling over to the next or previous day/month/year.
* Sub-millisecond precision (microseconds, nanoseconds) is preserved.
* @param hours - The hours to set (e.g., 0-23; 25 rolls over to next day's 1:00).
* @param minutes - The minutes to set (0-59; optional, defaults to current minutes).
* @param seconds - The seconds to set (0-59; optional, defaults to current seconds).
* @param milliseconds - The milliseconds to set (0-999; optional, defaults to current milliseconds).
* @returns The new timestamp in milliseconds since the epoch.
* @throws Error if excessive overflow causes forever loop to be reached.
* @throws TypeError if inputs are non-numeric.
*/
Datetime_global.prototype.setHours = function (hours, minutes, seconds, milliseconds) {
minutes = arguments.length > 1 ? minutes : this.time.minute;
seconds = arguments.length > 2 ? seconds : this.time.second;
milliseconds = arguments.length > 3 ? milliseconds : this.time.millisecond;
const try_time = {
hour: toNumber(hours),
minute: toNumber(minutes),
second: toNumber(seconds),
millisecond: toNumber(milliseconds),
}, time = overflowDatetime_global(this, try_time);
return (this.time = time).epochMilliseconds;
};
/**
* Sets the minutes, optionally seconds and milliseconds, modifying the instance in place.
* Handles overflow/underflow by rolling over to adjacent hours/days.
* @param minutes - The minutes (0-59).
* @param seconds - The seconds (0-59; optional, defaults to current seconds).
* @param milliseconds - The milliseconds (0-999; optional, defaults to current milliseconds).
* @returns The new timestamp in milliseconds since the epoch.
* @throws Error if excessive overflow causes recursion limit to be reached.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* dt.setMinutes(45);
* console.log(dt.toISOString()); // "2025-04-18T00:45:00.000Z"
*/
Datetime_global.prototype.setMinutes = function (minutes, seconds, milliseconds) {
seconds = arguments.length > 1 ? seconds : this.getSeconds();
milliseconds = arguments.length > 2 ? milliseconds : this.getMilliseconds();
return this.setHours(this.getHours(), minutes, seconds, milliseconds);
};
/**
* Sets the seconds, optionally milliseconds, modifying the instance in place.
* Handles overflow/underflow by rolling over to adjacent minutes/hours.
* @param seconds - The seconds (0-59).
* @param milliseconds - The milliseconds (0-999; optional, defaults to current milliseconds).
* @returns The new timestamp in milliseconds since the epoch.
* @throws Error if excessive overflow causes recursion limit to be reached.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* dt.setSeconds(45);
* console.log(dt.toISOString()); // "2025-04-18T00:00:45.000Z"
*/
Datetime_global.prototype.setSeconds = function (seconds, milliseconds) {
milliseconds = arguments.length > 1 ? milliseconds : this.getMilliseconds();
return this.setHours(this.getHours(), this.getMinutes(), seconds, milliseconds);
};
/**
* Sets the milliseconds, modifying the instance in place.
* Handles overflow/underflow by rolling over to adjacent seconds.
* @param milliseconds - The milliseconds (0-999).
* @returns The new timestamp in milliseconds since the epoch.
* @throws Error if excessive overflow causes recursion limit to be reached.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* dt.setMilliseconds(500);
* console.log(dt.toISOString()); // "2025-04-18T00:00:00.500Z"
*/
Datetime_global.prototype.setMilliseconds = function (milliseconds) {
return this.setHours(this.getHours(), this.getMinutes(), this.getSeconds(), milliseconds);
};
// UTC
/**
* Sets the year, optionally month and day, in UTC, modifying the instance in place.
*
* will convert to Date's calendar
* @param fullYear - The year (e.g., 2025).
* @param month - The month (0-11; optional, defaults to current UTC month).
* @param date - The day of the month (1-31; optional, defaults to current UTC day).
* @returns The new timestamp in milliseconds since the epoch.
* @throws RangeError if the components form an invalid date.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* dt.setUTCFullYear(2026);
* console.log(dt.toISOString()); // "2026-04-18T00:00:00.000Z"
*/
Datetime_global.prototype.setUTCFullYear = function (fullYear, month, date) {
const nanosecond = BigInt(this.time.nanosecond), microsecond = BigInt(this.time.microsecond) * 1000n, datetime = new Date(this.time.epochMilliseconds);
month = arguments.length > 1 ? month : datetime.getUTCMonth();
date = arguments.length > 2 ? date : datetime.getUTCDate();
const returnValue = BigInt(datetime.setUTCFullYear(fullYear, month, date));
this.time = new Temporal.ZonedDateTime(((returnValue * 1000000n) + microsecond + nanosecond), this.time.timeZoneId);
return Number(returnValue);
};
/**
* Sets the hours, optionally minutes, seconds, and milliseconds, in UTC, modifying the instance in place.
* Handles overflow/underflow by rolling over to adjacent days.
*
* will convert to Date's calendar
* @param hours - The hours (e.g., 0-23; 25 rolls over to next day's 1:00).
* @param minutes - The minutes (0-59; optional, defaults to current UTC minutes).
* @param seconds - The seconds (0-59; optional, defaults to current UTC seconds).
* @param milliseconds - The milliseconds (0-999; optional, defaults to current UTC milliseconds).
* @returns The new timestamp in milliseconds since the epoch.
* @throws RangeError if the components form an invalid date.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* dt.setUTCHours(15);
* console.log(dt.toISOString()); // "2025-04-18T15:00:00.000Z"
*/
Datetime_global.prototype.setUTCHours = function (hours, minutes, seconds, milliseconds) {
const nanosecond = BigInt(this.time.nanosecond), microsecond = BigInt(this.time.microsecond) * 1000n, date = new Date(this.time.epochMilliseconds);
minutes = arguments.length > 1 ? minutes : date.getUTCMinutes();
seconds = arguments.length > 2 ? seconds : date.getUTCSeconds();
milliseconds = arguments.length > 3 ? milliseconds : date.getUTCMilliseconds();
const returnValue = BigInt(date.setUTCHours(hours, minutes, seconds, milliseconds));
this.time = new Temporal.ZonedDateTime(((returnValue * 1000000n) + microsecond + nanosecond), this.time.timeZoneId);
return Number(returnValue);
};
/**
* sets the month based on `Date.prototype.setUTCFullYear`
* @param month the zero indexed month (0 to 11)
* @param date the day of the month.
*/
Datetime_global.prototype.setUTCMonth = function (month, date) {
date = arguments.length > 1 ? date : this.getUTCDate();
return this.setUTCFullYear(this.getUTCFullYear(), month, date);
};
/**
* sets the day based on `Date.prototype.setUTCFullYear`
* @param date the day of the month.
*/
Datetime_global.prototype.setUTCDate = function (date) {
return this.setUTCFullYear(this.getUTCFullYear(), this.getUTCMonth(), date);
};
/**
* sets the minutes based on `Date.prototype.setUTCHours`
* @param minutes the minutes (0 to 59)
* @param seconds the seconds (0 to 59)
* @param milliseconds the milliseconds (0 to 999)
*/
Datetime_global.prototype.setUTCMinutes = function (minutes, seconds, milliseconds) {
seconds = arguments.length > 1 ? seconds : this.getUTCSeconds();
milliseconds = arguments.length > 2 ? milliseconds : this.getUTCMilliseconds();
return this.setUTCHours(this.getUTCHours(), minutes, seconds, milliseconds);
};
/**
* sets the seconds based on `Date.prototype.setUTCHours`
* @param seconds the seconds (0 to 59)
* @param milliseconds the milliseconds (0 to 999)
*/
Datetime_global.prototype.setUTCSeconds = function (seconds, milliseconds) {
milliseconds = arguments.length > 1 ? milliseconds : this.getUTCMilliseconds();
return this.setUTCHours(this.getUTCHours(), this.getUTCMinutes(), seconds, milliseconds);
};
/**
* Returns the internal Temporal.ZonedDateTime instance.
* @returns The Temporal.ZonedDateTime.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.toTemporalZonedDateTime().toString());
* // "2025-04-18T00:00:00+00:00[UTC]"
*/
Datetime_global.prototype.toTemporalZonedDateTime = function () {
return this.time;
};
// custom
/**
* Sets the nanoseconds and optionally microseconds, modifying the instance in place.
* Preserves other date-time components.
* @param nanoseconds - The nanoseconds to set (default 0).
* @param microseconds - The microseconds to set (optional, defaults to current microseconds).
* @returns The new timestamp in nanoseconds since the epoch.
* @throws TypeError if inputs are not bigints.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* dt.setNanoseconds(500n);
* console.log(dt.getNanoseconds()); // 500n
*/
Datetime_global.prototype.setNanoseconds = function (nanoseconds = 0n, microseconds) {
const self_time = this.time, did_specify_microseconds = arguments.length > 1;
microseconds = BigInt(did_specify_microseconds ? (microseconds ?? 0) : self_time.microsecond);
return BigInt((this.time = new Temporal.ZonedDateTime(self_time.with({
microsecond: did_specify_microseconds ? 0 : self_time.microsecond,
nanosecond: 0, millisecond: self_time.millisecond,
}).epochNanoseconds + ((microseconds * 1000n) + BigInt(nanoseconds)), self_time.timeZoneId)).epochNanoseconds);
};
/**
* Returns the nanosecond and microseconds component of the date-time (0-999).
* @returns The nanoseconds and microseconds as a bigint.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00.000000500Z", "UTC");
* console.log(dt.getNanoseconds()); // 500n
*/
Datetime_global.prototype.getUTCNanoseconds = Datetime_global.prototype.getNanoseconds = function () {
return (BigInt(this.time.microsecond) * 1000n) + BigInt(this.time.nanosecond);
};
/**
* Formats a timezone offset in minutes as a UTC string (e.g., "UTC+0000").
* @param offset - The offset in minutes (positive for west of UTC, negative for east).
* @returns The formatted offset string.
* @example
* console.log(Datetime_global.getUTCOffset(240)); // "UTC-0400"
*/
Datetime_global.getUTCOffset = function (offset) {
if (isNaN(offset))
return 'UTC+Error';
const sign = offset > 0 ? "-" : "+", absOffset = Math.abs(offset);
const pad = (n) => padNumber(n).replace(/^\+/, '');
const hours = pad(Math.trunc(absOffset / 60));
const minutes = pad(absOffset % 60);
return `UTC${sign}${hours}${minutes}`;
};
/**
* Updates the innerText of HTML <time> elements with formatted date-time strings.
* Uses the `data-datetime-global-format` attribute for the format (default: "D M d Y H:i:s \U\T\CO (e)")
* and `data-iana-timezone` for the timezone (default: local timezone).
* @param timetags - A NodeList or Array of HTMLTimeElement.
* @throws RangeError if a time element's dateTime attribute is invalid.
* @example
* // HTML: <time datetime="2025-04-18T00:00:00Z" data-datetime-global-format="[offsetFromNow]"></time>
* Datetime_global.htmlToCurrentTime(document.querySelectorAll('time'));
* // Updates innerText to e.g., "in 5 days"
*/
Datetime_global.htmlToCurrentTime = function (timetags = []) {
const now = Temporal.Now.zonedDateTimeISO();
Array.from(timetags).forEach(function (each) {
const tz = each.getAttribute('data-iana-timezone') ?? Temporal.Now.timeZoneId(), d = new Datetime_global(Date.parse(each.dateTime), tz), f = each.getAttribute('data-datetime-global-format') ?? 'D M d Y H:i:s \\U\\T\\CO (e)';
switch (f) {
case "[TemporalOffset]":
{
const target = d.toTemporalZonedDateTime();
const isFuture = target.epochMilliseconds > now.epochMilliseconds, largestUnit = 'days';
const duration = isFuture ? now.until(target, { largestUnit }) : target.until(now, { largestUnit });
const parts = [];
if (duration.days)
parts.push(`${duration.days} day${duration.days !== 1 ? 's' : ''}`);
if (duration.hours)
parts.push(`${duration.hours} hour${duration.hours !== 1 ? 's' : ''}`);
if (duration.minutes)
parts.push(`${duration.minutes} minute${duration.minutes !== 1 ? 's' : ''}`);
if (duration.seconds && parts.length === 0)
parts.push(`${duration.seconds} second${duration.seconds !== 1 ? 's' : ''}`);
const join = parts.map(s => s.trim()).join(', ');
each.innerText = isFuture ? 'in ' + join : join + ' ago';
}
return;
}
each.innerText = d.format(f);
});
};
/**
* Formats the time difference between now and the given date as a human-readable string.
* @param date The timestamp (in milliseconds) to compare against the current time.
* @returns A string like "now", "in 30 seconds", or "5 minutes ago".
*/
export const formatOffsetFromNow = function (date) {
const diffMs = (+date) - Date.now();
const absDiffMs = Math.abs(diffMs);
const isFuture = diffMs > 0;
const seconds = Math.floor(absDiffMs / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (absDiffMs < 1000) {
return "now";
}
else if (seconds < 60) {
return `${isFuture ? "in " : ""}${seconds} second${seconds === 1 ? "" : "s"}${isFuture ? "" : " ago"}`;
}
else if (minutes < 60) {
return `${isFuture ? "in " : ""}${minutes} minute${minutes === 1 ? "" : "s"}${isFuture ? "" : " ago"}`;
}
else if (hours < 24) {
return `${isFuture ? "in " : ""}${hours} hour${hours === 1 ? "" : "s"}${isFuture ? "" : " ago"}`;
}
else {
return `${isFuture ? "in " : ""}${days} day${days === 1 ? "" : "s"}${isFuture ? "" : " ago"}`;
}
};
/**
* applies the UTC time to the `Datetime_global`
*
* @returns {Datetime_global}
*/
Datetime_global.prototype.toUTCTimezone = function () {
return this.toTimezone('UTC');
};
/**
* applies the system's LocalTime to the `Datetime_global`
*
* @returns {Datetime_global}
*/
Datetime_global.prototype.toLocalTime = function () {
return this.toTimezone(Temporal.Now.timeZoneId());
};
/**
* Returns the day of the week (0 = Sunday, 1 = Monday, ..., 6 = Saturday).
* @alias getDay
* @returns The day of the week (0-6).
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC"); // Friday
* console.log(dt.getDayNumberWeek()); // 5
*/
Datetime_global.prototype.getDayNumberWeek = function () {
return this.getDay();
};
/**
* Returns the day of the month (1-31).
* @alias getDate
* @returns The day of the month.
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.getDayNumberMonth()); // 18
*/
Datetime_global.prototype.getDayNumberMonth = Datetime_global.prototype.getDayNumber = function () {
return this.getDate();
};
/**
* Returns the abbreviated weekday name (e.g., "Mon", "Tue") in en-US locale.
* @returns The weekday name. (oneOf "Sun" | "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" )
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC"); // Friday
* console.log(dt.getDayName()); // "Fri"
*/
Datetime_global.prototype.getDayName = function () {
return Datetime_global.daynames[this.getDay()];
};
/**
* Returns the abbreviated month name (e.g., "Jan", "Feb") in en-US locale.
* @returns The month name. (oneOf "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun" | "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec" )
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.getMonthName()); // "Apr"
*/
Datetime_global.prototype.getMonthName = function () {
return Datetime_global.monthnames[this.withCalender('iso8601').getMonth()];
};
/**
* Returns the full weekday name (e.g., "Monday", "Tuesday") in en-US locale.
* @returns The weekday name. (OneOf "Sunday" | "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday")
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC"); // Friday
* console.log(dt.getFullDayName()); // "Friday"
*/
Datetime_global.prototype.getFullDayName = function () {
return Datetime_global.daynamesFull[this.getDay()];
};
/**
* Returns the full month name (e.g., "January", "February") in en-US locale.
* @returns The full month name. (oneOf "January" | "February" | "March" | "April" | "May" | "June" | "July" | "August" | "September" | "October" | "November" | "December")
* @example
* const dt = new Datetime_global("2025-04-18T00:00:00Z", "UTC");
* console.log(dt.getFullMonthName()); // "April"
*/
Datetime_global.prototype.getFullMonthName = function () {
return Datetime_global.monthnamesFull[this.withCalender('iso8601').getMonth()];
};
/**
* @see Temporal.ZonedDateTime.toLocaleString
* @param locales
* @param options
*/
Datetime_global.prototype.toLocaleString = function (locales, options) {
return this.time.toLocaleString(locales, options);
};
/**
* Converts the internal datetime value to a GMT (UTC) string representation.
*
* This method provides a standardized, human-readable string of the datetime
* in Greenwich Mean Time (UTC), following the format produced by
* `Date.prototype.toUTCString()`. It is primarily intended for display purposes
* where a clear, unambiguous representation of the time in UTC is required.
*
* Internally, this method delegates to `toDate()`, which is expected to return a
* native JavaScript `Date` instance representing the same point in time as this
* `Datetime_global` object.
*
* #### Example
* ```js
* const dt = new Datetime_global(...);
* console.log(dt.toGMTString());
* // Output: "Mon, 09 Jun 2025 12:00:00 GMT"
* ```
*
* @method toGMTString
* @memberof Datetime_global
* @instance
* @returns {string} A GMT-formatted date string compliant with `Date.prototype.toUTCString()`.
*/
Datetime_global.prototype.toGMTString = function () {
return this.toDate().toUTCString();
};
/**
* Converts the internal datetime value to a UTC string representation.
*
* This method provides a standardized, human-readable string of the datetime
* in UTC, following the format produced by
* It is primarily intended for display purposes
* where a clear, unambiguous representation of the time in UTC is required.
*
* #### Example
* ```js
* const dt = new Datetime_global(...);
* console.log(dt.toUTCString());
* // Output: "Mon, 09 Jun 2025 12:00:00 UTC"
* ```
*
* @method toGMTString
* @memberof Datetime_global
* @instance
* @returns {string} A UTC-formatted date string.
* @note php 'D, d M Y H:i:s \\U\\T\\C'
*/
Datetime_global.prototype.toUTCString = function () {
return this.toUTCTimezone().format('D, d M Y H:i:s \\U\\T\\C');
};
Datetime_global.prototype.toDateString = function () {
return this.format('D M d Y');
};
Datetime_global.prototype.toTimeString = function () {
return this.format('H:i:s \\U\\T\\CO (e)');
};
/**
* Formats the date-time using a PHP-like format pattern with placeholders (e.g., `Y`, `m`, `d`).
* Supports special patterns (e.g., `[toMYSQLi]`) and escaped characters (e.g., `\Y`).
* @param pattern - The format string with placeholders or special patterns.
* @returns The formatted date-time string.
* @throws Error if the `o` placeholder (ISO-8601 year) is used.
* @example
* const dt = new Datetime_global(new Date(2025, 3, 18), "UTC");
* dt.format("Y-m-d H:i:s"); // "2025-04-18 00:00:00"
* dt.format("[toMYSQLi]"); // "2025-04-18 00:00:00"
* dt.format("D, Y-m-d H:i:s.u \\U\\T\\CO (e)"); // "Fri, 2025-04-18 00:00:00.000000 UTC+0000 (UTC)"
* @see https://www.php.net/manual/en/datetime.format.php for placeholder details.
*/
Datetime_global.prototype.format = function (pattern) {
const string = pattern ?? '';
//(new this.constructor(this, this?.time?.timeZoneId))
const datetime_local = this.withCalender(), pad = (n, z = 2) => padNumber(n, z).replace(/^\+/, '');
const hour24 = pad(datetime_local.getHours()), dayName = datetime_local.getDayName();
const iso8601 = datetime_local, dayNameFull = datetime_local.getFullDayName();
const dayNumberMonth = pad(datetime_local.getDayNumberMonth()), N = iso8601.time.dayOfWeek.toString(), //iso8601.time.dayOfWeek
W = iso8601.time?.weekOfYear?.toString() ?? 'undefined', w = iso8601.getDay().toString(), z = iso8601.time.daysInYear.toString(), m = pad(datetime_local.getMonth() + 1), M = datetime_local.getMonthName(), F = datetime_local.getFullMonthName(), hour12 = pad(+hour24 === 0 ? 12 : +hour24), dayInMonth = datetime_local.time.daysInMonth.toString(), leap = datetime_local.time.inLeapYear ? '1' : '0', X = pad(datetime_local.getFullYear(), 4), getYear = pad(datetime_local.getYear(), 2), minutes = pad(datetime_local.getMinutes()), seconds = pad(datetime_local.getSeconds()), datetime_timezone = datetime_local.time.timeZoneId, offset = Datetime_global.getUTCOffset(datetime_local.getTimezoneOffset()).replace(/UTC/, ''), currentDate = datetime_local.toDate(), B = toSwatchInternetTime(currentDate), microseconds = `${pad(datetime_local.getMilliseconds(), 3)}${pad(datetime_local.time.microsecond, 3)}`, milliseconds =