How to initialize a JavaScript Date to a particular time zone
I have date time in a particular timezone as a string and I want to convert this to the local time. But, I don't know how to set the timezone in the Date object.
For example, I have Feb 28 2013 7:00 PM ET,
then I can
var mydate = new Date();
mydate.setFullYear(2013);
mydate.setMonth(02);
mydate.setDate(28);
mydate.setHours(7);
mydate.setMinutes(00);
As far as I know, I can either set the UTC time or local time. But, how do I set time in another timezone?
I tried to use the add/subtract the offset from UTC but I don't know how to counter daylight savings. Am not sure if I am heading the right direction.
How can I go about converting time from a different timezone to local time in javascript?
Solution 1:
Background
JavaScript's Date
object tracks time in UTC internally, but typically accepts input and produces output in the local time of the computer it's running on. It has very few facilities for working with time in other time zones.
The internal representation of a Date
object is a single number, representing the number of milliseconds that have elapsed since 1970-01-01 00:00:00 UTC
, without regard to leap seconds.
There is no time zone or string format stored in the Date object itself.
When various functions of the Date
object are used, the computer's local time zone is applied to the internal representation. If the function produces a string, then the computer's locale information may be taken into consideration to determine how to produce that string. The details vary per function, and some are implementation-specific.
The only operations the Date
object can do with non-local time zones are:
-
It can parse a string containing a numeric UTC offset from any time zone. It uses this to adjust the value being parsed, and stores the UTC equivalent. The original local time and offset are not retained in the resulting
Date
object. For example:var d = new Date("2020-04-13T00:00:00.000+08:00"); d.toISOString() //=> "2020-04-12T16:00:00.000Z" d.valueOf() //=> 1586707200000 (this is what is actually stored in the object)
-
In environments that have implemented the ECMASCript Internationalization API (aka "Intl"), a
Date
object can produce a locale-specific string adjusted to a given time zone identifier. This is accomplished via thetimeZone
option totoLocaleString
and its variations. Most implementations will support IANA time zone identifiers, such as'America/New_York'
. For example:var d = new Date("2020-04-13T00:00:00.000+08:00"); d.toLocaleString('en-US', { timeZone: 'America/New_York' }) //=> "4/12/2020, 12:00:00 PM" // (midnight in China on Apring 13th is noon in New York on April 12th)
Most modern environments support the full set of IANA time zone identifiers (see the compatibility table here). However, keep in mind that the only identifier required to be supported by Intl is
'UTC'
, thus you should check carefully if you need to support older browsers or atypical environments (for example, lightweight IoT devices).
Libraries
There are several libraries that can be used to work with time zones. Though they still cannot make the Date
object behave any differently, they typically implement the standard IANA timezone database and provide functions for using it in JavaScript. Modern libraries use the time zone data supplied by the Intl API, but older libraries typically have overhead, especially if you are running in a web browser, as the database can get a bit large. Some of these libraries also allow you to selectively reduce the data set, either by which time zones are supported and/or by the range of dates you can work with.
Here are the libraries to consider:
Intl-based Libraries
New development should choose from one of these implementations, which rely on the Intl API for their time zone data:
- Luxon (successor of Moment.js)
- date-fns-tz (extension for date-fns)
Non-Intl Libraries
These libraries are maintained, but carry the burden of packaging their own time zone data, which can be quite large.
- js-joda/timezone (extension for js-joda)
- moment-timezone* (extension for Moment.js)
- date-fns-timezone (extension for older 1.x of date-fns)
- BigEasy/TimeZone
- tz.js
* While Moment and Moment-Timezone were previously recommended, the Moment team now prefers users chose Luxon for new development.
Discontinued Libraries
These libraries have been officially discontinued and should no longer be used.
- WallTime-js
- TimeZoneJS
Future Proposals
The TC39 Temporal Proposal aims to provide a new set of standard objects for working with dates and times in the JavaScript language itself. This will include support for a time zone aware object.
Solution 2:
As Matt Johnson said
If you can limit your usage to modern web browsers, you can now do the following without any special libraries:
new Date().toLocaleString("en-US", {timeZone: "America/New_York"})
This isn't a comprehensive solution, but it works for many scenarios that require only output conversion (from UTC or local time to a specific time zone, but not the other direction).
So although the browser can not read IANA timezones when creating a date, or has any methods to change the timezones on an existing Date object, there seems to be a hack around it:
function changeTimezone(date, ianatz) {
// suppose the date is 12:00 UTC
var invdate = new Date(date.toLocaleString('en-US', {
timeZone: ianatz
}));
// then invdate will be 07:00 in Toronto
// and the diff is 5 hours
var diff = date.getTime() - invdate.getTime();
// so 12:00 in Toronto is 17:00 UTC
return new Date(date.getTime() - diff); // needs to substract
}
// E.g.
var here = new Date();
var there = changeTimezone(here, "America/Toronto");
console.log(`Here: ${here.toString()}\nToronto: ${there.toString()}`);