JavaScript Date Timezone Issue

javascript Date timezone issue

When parsing a string to a Date in JavaScript, a value that is in YYYY-MM-DD format is interpreted as a UTC value, rather than a local-time value.

The key is that the parts are separated by hyphens, and that there is no time zone information in the string. The ECMAScript 5.1 Spec says in §15.9.1.15:

... The value of an absent time zone offset is “Z”.

That means, if you don't specify an offset, it will assume you meant UTC.

Note that since this is the opposite of what ISO-8601 says, this is behavior has been changed in ECMAScript 2015 (6.0), which says in §20.3.1.16:

... If the time zone offset is absent, the date-time is interpreted as a local time.

Therefore, when this provision of ES6 is implemented properly, string values of this format that used to be interpreted as UTC will be interpreted as local time instead. I've blogged about this here.

The workaround is simple. Replace the hyphens with slashes:

var s = "2000-01-01";
var dt = new Date(s.replace(/-/g, '/'));

Another workaround that is acceptable is to assign a time of noon instead of midnight to the date. This will be parsed as local time, and is far enough away to avoid any DST conflicts.

var s = "2000-01-01";
var dt = new Date(s + "T12:00:00");

Alternatively, consider a library like moment.js which is much more sensible.

var s = "2000-01-01";
var dt = moment(s, 'YYYY-MM-DD').toDate();

Timezone issue in javascript Date object

I solved this problem by executing new Date() on the client side and then passing in url to the server for further action.

Client side code =>

 <button onclick="createLogin()" class="btn btn-outline-primary btn-lg btn-block entryBtn">
CREATE LOGIN ENTRY
</button>

<script>
function createLogin() {
let t = new Date();
console.log(t);

let url = '/logEntry/' + t;
window.location = url;
}
</script>

Server side code =>

app.get('/logEntry/:date', function(req, res) {
if (req.isAuthenticated()) {
const now = req.params.date;
const nowDayTime = now.substring(0, 25);
const timeZone = now.substring(25, now.length);
const rawNow = Date.now();
const post = new Post({
username: nameUser,
entryDayTime: nowDayTime,
entryTimeZone: timeZone,
rawEntry: rawNow,
complete: false
});
post.save(function(err) {
if (err) {
console.log(err);
}
res.redirect('/logged');
});
} else {
res.redirect('/');
}
});

Sample Image

Avoid timezone correction for JavaScript Date

Values passed to the Date constructor are treated as local, toISOString uses UTC. Unfortunately ECMAScript doesn't have a timezone–free, date–only form.

If you want to use toISOString to format the timestamp, then one solution is to parse the values as UTC initially, e.g.

sendDate(d) {
let date = new Date(Date.UTC(this.year, this.month, d));
htmx.ajax("GET", "/some/url", { values: { "date": date.toISOString() } });
}

Example:

let d = new Date()
let year = d.getFullYear();
let month = d.getMonth()
let day = d.getDate();
let date = new Date(Date.UTC(year, month, day))
// Always shows the current local date as 00:00:00Z
console.log( date.toISOString() );

Create a Date with a set timezone without using a string representation

using .setUTCHours() it would be possible to actually set dates in UTC-time, which would allow you to use UTC-times throughout the system.

You cannot set it using UTC in the constructor though, unless you specify a date-string.

Using new Date(Date.UTC(year, month, day, hour, minute, second)) you can create a Date-object from a specific UTC time.

Datetime timezone conversion issue in Typescript

You can convert a given date to a localized string for a timezone using

new Date([your date].toLocaleString("en", { timeZone: [some timezone] }));

Here's a small helper:

const dt = new Date(`2022/01/09`);
document.querySelector(`pre`).textContent = `now in\n \u2713 Kolkata: ${
dateTime4TZ(`Asia/Kolkata`)}\n \u2713 Amsterdam: ${
dateTime4TZ(`Europe/Amsterdam`)}\n \u2713 Tokyo: ${
dateTime4TZ(`Asia/Tokyo`)}\n \u2713 Auckland: ${
dateTime4TZ(`Pacific/Auckland`)}\n\n"2022/01/09" in\n \u2713 Kolkata: ${
dateTime4TZ(`Asia/Kolkata`, dt)}\n \u2713 Amsterdam: ${
dateTime4TZ(`Europe/Amsterdam`, dt)}\n \u2713 Tokyo: ${
dateTime4TZ(`Asia/Tokyo`, dt)}\n \u2713 Auckland: ${
dateTime4TZ(`Pacific/Auckland`, dt)}`;

function dateTime4TZ(timeZone, dt = new Date) {
const pad = (nr, len=2) => `${nr}`.padStart(len, `0`);
const localDT = new Date(dt.toLocaleString("en", { timeZone }));
return `${localDT.getFullYear()}-${
pad(localDT.getMonth() + 1)}-${
pad(localDT.getDate())}T${
pad(localDT.getHours())}:${
pad(localDT.getMinutes())}:${
pad(localDT.getSeconds())}.${
pad(localDT.getMilliseconds(), 3)}Z`;
};
<pre></pre>

Creating timezone independent dates in Javascript?

From the ECMA standard of the Date.parse method:

When the UTC offset representation is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time.

What is happening is that New Date() implicitly calls Date.parse on the string. The "2000-01-01" version conforms to a Date Time String Format with a missing offset representation, so it is assumed you mean UTC.

When you use "2000/01/01" as input the standard has this to say:

If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.

So in short the browser can do what they want. And in your case it assumes you mean the offset of the local time, so whichever offset you are located in gets added when you convert to UTC.

For consistent results, perhaps you want to take a look at Date.UTC

new Date(Date.UTC(2000, 0, 1))

If you need to pass in an ISO string make sure you include the time offset of +00:00 (is often abbreviated with z)

new Date("2000-01-01T00:00:00Z");

If you want to later set the date to something different, use an equivalent UTC setter method (e.g. setUTCHours).

When you retrieve the date, also make sure to use the UTC getter methods (e.g. getUTCMonth).

const date = new Date("2000-01-01T00:00:00Z");

console.log(date.getUTCDate());
console.log(date.getUTCMonth());
console.log(date.getUTCFullYear());


Related Topics



Leave a reply



Submit