Date.toISOString() but local time instead of UTC
My version:
// https://stackoverflow.com/questions/10830357/javascript-toisostring-ignores-timezone-offset/37661393#37661393
// https://stackoverflow.com/questions/49330139/date-toisostring-but-local-time-instead-of-utc/49332027#49332027
function toISOLocal(d) {
const z = n => ('0' + n).slice(-2);
let off = d.getTimezoneOffset();
const sign = off < 0 ? '+' : '-';
off = Math.abs(off);
return new Date(d.getTime() - (d.getTimezoneOffset() * 60000)).toISOString().slice(0, -1) + sign + z(off / 60 | 0) + ':' + z(off % 60);
}
console.log(toISOLocal(new Date()));
There is limited built-in support for formatting date strings with timezones in ECMA-262, there is either implementation dependent toString and toLocaleString methods or toISOString, which is always UTC. It would be good if toISOString allowed a parameter to specify UTC or local offset (where the default is UTC).
Writing your own function to generate an ISO 8601 compliant timestamp with local offset isn't difficult:
function toISOLocal(d) {
var z = n => ('0' + n).slice(-2);
var zz = n => ('00' + n).slice(-3);
var off = d.getTimezoneOffset();
var sign = off > 0? '-' : '+';
off = Math.abs(off);
return d.getFullYear() + '-'
+ z(d.getMonth()+1) + '-' +
z(d.getDate()) + 'T' +
z(d.getHours()) + ':' +
z(d.getMinutes()) + ':' +
z(d.getSeconds()) + '.' +
zz(d.getMilliseconds()) +
sign + z(off/60|0) + ':' + z(off%60);
}
console.log(toISOLocal(new Date()));
The trick is to adjust the time by the timezone, and then use toISOString()
. You can do this by creating a new date with the original time and subtracting by the timezone offssetfrom the original time:
var d = new Date("Sat Jul 21 2018 14:00:00 GMT+0200");
var newd = new Date(d.getTime() - d.getTimezoneOffset()*60000);
console.log(newd.toISOString())
Alternatively, you can simply adjust the original date:
var d = new Date("Sat Jul 21 2018 14:00:00 GMT+0200");
d = new Date(d.getTime() - d.getTimezoneOffset()*60000);
console.log(d.toISOString())
For your convenience, the result from .getTime()
is the number of milliseconds since 1 January 1970. However, getTimezoneOffset()
gives a time zone difference from UTC in minutes; that’s why you need to multiply by 60000
to get this in milliseconds.
Of course, the new time is still relative to UTC, so you’ll have to ignore the Z
at the end:
d = d.slice(0,-1);