Skip to content Skip to sidebar Skip to footer

Working With Different Timezones In Javascript

I am working on a cloud based application which deals extensively with date and time values, for users across the world. Consider a scenario, in JavaScript, where my machine is in

Solution 1:

First, let's talk about the code in your question.

let india_date = newDate()

You have named this variable india_date, but the Date object will only reflect India if the code is run on a computer set to India's time zone. If it is run on a computer with a different time zone, it will reflect that time zone instead. Keep in mind that internally, the Date object only tracks a UTC based timestamp. The local time zone is applied when functions and properties that need local time are called - not when the Date object is created.

add it's timezone offset value

let uts_ms = india_date.getTime() + india_date.getTimezoneOffset()

This approach is incorrect. getTime() already returns a UTC based timestamp. You don't need to add your local offset. (also, the abbreviation is UTC, not UTS.)

Now add california's timezone offset value

let california_ms = utc_ms + getCaliforniaTimezoneOffsetMS()

Again, adding an offset is incorrect. Also, unlike India, California observes daylight saving time, so part of the year the offset will be 480 (UTC-8), and part of the year the offset will be 420 (UTC-7). Any function such as your getCaliforniatimezoneOffsetMS would need to have the timestamp passed in as a parameter to be effective.

and finally the date object

letcalifornia_date: Date = newDate(california_ms)

When the Date constructor is passed a numeric timestamp, it must be in terms of UTC. Passing it this california_ms timestamp is actually just picking a different point in time. You can't change the Date object's behavior to get it to use a different time zone just by adding or subtracting an offset. It will still use the local time zone of where it runs, for any function that requires a local time, such as .toString() and others.

There is only one scenario where this sort of adjustment makes sense, which is a technique known as "epoch shifting". The timestamp is adjusted to shift the base epoch away from the normal 1970-01-01T00:00:00Z, thus allowing one to take advantage of the Date object's UTC functions (such as getUTCHours and others). The catch is: once shifted, you can't ever use any of the local time functions on that Date object, or pass it to anything else that expects the Date object to be a normal one. Epoch shifting done right is what powers libraries like Moment.js. Here is another example of epoch shifting done correctly.

But in your example, you are shifting (twice in error) and then using the Date object as if it were normal and not shifted. This can only lead to errors, evident by the time zone shown in toString output, and will arise mathematically near any DST transitions of the local time zone and the intended target time zone. In general, you don't want to take this approach.

Instead, read my answer on How to initialize a JavaScript Date to a particular time zone. Your options are listed there. Thanks.

Solution 2:

JavaScript Date objects store date and time in UTC but the toString() method is automatically called when the date is represented as a text value which displays the date and time in the browser's local time zone. So, when you want to convert a datetime to a time zone other than your local time, you are really converting from UTC to that time zone (not from your local time zone to another time zone).

If your use case is limited to specific browsers and you are flexible on formatting (since browsers may differ in how they display date string formats), then you may be able to use toLocaleString(), but browsers like Edge, Android webview, etc do not fully support the locales and options parameters.

Following example sets both the locale and timezone to output the date in a local format that may vary from browser to browser.

const dt = newDate();
const kolkata = dt.toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' });
const la = dt.toLocaleString('en-US', { timeZone: 'America/Los_Angeles' });
console.log('Kolkata:', kolkata);
// example output: Kolkata: 19/3/2019, 7:36:26 pmconsole.log('Los Angeles:', la);
// example output: Los Angeles: 3/19/2019, 7:06:26 AM

You could also use Moment.js and Moment Timezone to convert date and time to a time zone other than your local time zone. For example:

const dt = moment();
const kolkata = dt.tz('Asia/Kolkata').format();
const la = dt.tz('America/Los_Angeles').format();
console.log(kolkata);
// example output: 2019-03-19T19:37:11+05:30console.log(la);
// example output: 2019-03-19T07:07:11-07:00
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.23/moment-timezone-with-data.min.js"></script>

Solution 3:

Well, you really do kind of have to convert anytime you want to change the display, but it's not as bad as you think.

First, store all time as UTC. Probably using the milliseconds format, e.g. Date.UTC().

Second, do all manipulation / comparison using that stored info.

Third, if your cloud-based application has an API that API should only talk in terms of UTC as well, though you could provide the ISO string if you prefer that to the MS, or if you expect clients to handle that better.

Fourth and finally, only in the UI should you do the final conversion to the local date/time string, either with the method you're describing or using a library such as momentjs

Solution 4:

new Date creates a Date object with a time value that is UTC. If you can guarantee support for the timeZone option of toLocaleString (e.g. corporate environment with a controlled SOE), you can use it to construct a timestamp in any time zone and any format, but it can be a bit tedious. Support on the general web may be lacking. A library would be preferred in that case if you need it to work reliably.

E.g. to get values for California, you can use toLocaleString and "America/Los_Angeles" for the timeZone option:

var d = newDate();

// Use the default implementation formatconsole.log(d.toLocaleString(undefined, {timeZone:'America/Los_Angeles'}));

// Customised formatvar weekday = d.toLocaleString(undefined, {weekday:'long', timeZone:'America/Los_Angeles'});
var day = d.toLocaleString(undefined, {day:'numeric', timeZone:'America/Los_Angeles'});
var month = d.toLocaleString(undefined, {month:'long', timeZone:'America/Los_Angeles'});
var year = d.toLocaleString(undefined, {year:'numeric', timeZone:'America/Los_Angeles'});
var hour = d.toLocaleString(undefined, {hour:'numeric',hour12: false, timeZone:'America/Los_Angeles'});
var minute = d.toLocaleString(undefined, {minute:'2-digit', timeZone:'America/Los_Angeles'});
var ap = hour > 11? 'pm' : 'am';
hour = ('0' + (hour % 12 || 12)).slice(-2);

console.log(`The time in Los Angeles is ${hour}:${minute}${ap} on ${weekday}, ${day}${month}, ${year}`);

Getting the timezone name is a little more difficult, it's difficult to get it without other information.

Post a Comment for "Working With Different Timezones In Javascript"