JavaScript Date
objects don't store timezone information. They use the system timezone, and that's it. So once you have a Date
, you've lost timezone information (other than the current system's timezone).
From a Date
, you can get the current timezone offset, and you can form a string in ISO-8601 format using that timezone offset:
function pad(x, width = 2, char = "0") {
return String(x).padStart(width, char);
}
function toLocalISOString(dt) {
const offset = dt.getTimezoneOffset();
const absOffset = Math.abs(offset);
const offHours = Math.floor(absOffset / 60);
const offStr = pad(offHours) + ":" + pad(absOffset - offHours * 60);
return [
String(dt.getFullYear()),
"-",
pad(dt.getMonth() + 1),
"-",
pad(dt.getDate()),
"T",
pad(dt.getHours()),
":",
pad(dt.getMinutes()),
":",
pad(dt.getSeconds()),
".",
dt.getMilliseconds(),
offset <= 0 ? "+" : "-",
offStr
].join("");
}
console.log(toLocalISOString(new Date()));
...but an offset isn't a timezone; an offset only tells you how many hours and minutes offset from UTC a date/time is, not what rules govern it.
In any modern browser (not IE11), you can get the actual timezone from Intl.DateTimeFormat().resolvedOptions().timeZone
, which will give you an IANA string like "Europe/London"
. You could include that in your custom string, perhaps conditionally based on being able to get it:
function pad(x, width = 2, char = "0") {
return String(x).padStart(width, char);
}
function toLocalISOString(dt) {
const offset = dt.getTimezoneOffset();
const absOffset = Math.abs(offset);
const offHours = Math.floor(absOffset / 60);
const offStr = pad(offHours) + ":" + pad(absOffset - offHours * 60);
let parts = [
String(dt.getFullYear()),
"-",
pad(dt.getMonth() + 1),
"-",
pad(dt.getDate()),
"T",
pad(dt.getHours()),
":",
pad(dt.getMinutes()),
":",
pad(dt.getSeconds()),
".",
dt.getMilliseconds(),
offset <= 0 ? "+" : "-",
offStr
];
if (typeof Intl === "object" && Intl.DateTimeFormat) {
try {
parts.push(
" (",
Intl.DateTimeFormat().resolvedOptions().timeZone,
")"
);
} catch (e) {
}
}
return parts.join("");
}
console.log(toLocalISOString(new Date()));