Let's say we have this datetime:
var d = new Date("Sat Jul 21 2018 14:00:00 GMT+0200");
Exporting it as a string (console.log(d)
) gives inconsistent results among browsers:
Sat Jul 21 2018 14:00:00 GMT+0200 (Paris, Madrid (heure d’été))
with Chrome
Sat Jul 21 14:00:00 UTC+0200 2018
with Internet Explorer, etc.
so we can't send datetime to a server with an unconsistent format.
The natural idea then would be to ask for an ISO8601 datetime, and use d.toISOString();
but it gives the UTC datetime: 2018-07-21T12:00:00.000Z
whereas I would like the local-timezone time instead:
2018-07-21T14:00:00+0200
or
2018-07-21T14:00:00
How to get this (without relying on a third party dependency like momentjs)?
I tried this, which seems to work, but isn't there a more natural way to do it?
var pad = function(i) { return (i < 10) ? '0' + i : i; };
var d = new Date("Sat Jul 21 2018 14:00:00 GMT+0200");
Y = d.getFullYear();
m = d.getMonth() + 1;
D = d.getDate();
H = d.getHours();
M = d.getMinutes();
S = d.getSeconds();
s = Y + '-' + pad(m) + '-' + pad(D) + 'T' + pad(H) + ':' + pad(M) + ':' + pad(S);
console.log(s);
The toISOString() method returns a string in simplified extended ISO format (ISO 8601), which is always 24 or 27 characters long ( YYYY-MM-DDTHH:mm:ss. sssZ or ±YYYYYY-MM-DDTHH:mm:ss. sssZ , respectively). The timezone is always zero UTC offset, as denoted by the suffix Z .
Add the local time offset to the UTC time. For example, if your local time offset is -5:00, and if the UTC time is shown as 11:00, add -5 to 11. The time setting when adjusted for offset is 06:00 (6:00 A.M.).
The date. toISOString() method is used to convert the given date object's contents into a string in ISO format (ISO 8601) i.e, in the form of (YYYY-MM-DDTHH:mm:ss. sssZ or ±YYYYYY-MM-DDTHH:mm:ss. sssZ).
Use the Date() constructor to convert UTC to local time, e.g. new Date(utcDateStr) . Passing a date and time string in ISO 8601 format to the Date() constructor converts the UTC date and time to local time. Copied!
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);
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()));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With