720

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?

5
  • 4
    This answer may help you
    – DarkAjax
    Commented Feb 28, 2013 at 17:26
  • 14
    Date objects don't have a timezone, they are UTC.
    – RobG
    Commented Nov 14, 2019 at 20:42
  • 3
    worth reading this article medium.com/@toastui/…, the conclusion is you can't in JavaScript but you can use libraries like Moment Timezone to do it
    – Neekey
    Commented Aug 9, 2020 at 9:56
  • 15
    @JohnLord No, the local getters simply convert the stored UTC time into the host timezone. For example, do d = new Date() then d.getHours() in the console, change your computer's time zone by an hour, and try d.getHours() again. There is no local time zone information stored in d.
    – lynn
    Commented Dec 8, 2020 at 2:15
  • 2
    I also wrote an article around this issue at medium.com/@EyeDin/… . Might worth reading. :)
    – Aidin
    Commented Nov 14, 2021 at 9:44

24 Answers 24

907

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 - namely timestamp - 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 the timeZone option to toLocaleString 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 April 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:

Non-Intl Libraries

These libraries are maintained, but carry the burden of packaging their own time zone data, which can be quite large.

* 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.

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.

Common Errors

There are several approaches that are often tried, which are in error and should usually be avoided.

Re-Parsing

new Date(new Date().toLocaleString('en', {timeZone: 'America/New_York'}))

The above approach correctly uses the Intl API to create a string in a specific time zone, but then it incorrectly passes that string back into the Date constructor. In this case, parsing will be implementation-specific, and may fail entirely. If successful, it is likely that the resulting Date object now represents the wrong instant in time, as the computer's local time zone would be applied during parsing.

Epoch Shifting

var d = new Date();
d.setTime(d.getTime() + someOffset * 60000);

The above approach attempts to manipulate the Date object's time zone by shifting the Unix timestamp by some other time zone offset. However, since the Date object only tracks time in UTC, it actually just makes the Date object represent a different point in time.

The same approach is sometimes used directly on the constructor, and is also invalid.

Epoch Shifting is sometimes used internally in date libraries as a shortcut to avoid writing calendar arithmetic. When doing so, any access to non-UTC properties must be avoided. For example, once shifted, a call to getUTCHours would be acceptable, but a call to getHours would be invalid because it uses the local time zone.

It is called "epoch shifting", because when used correctly, the Unix Epoch (1970-01-01T00:00:00.000Z) is now no longer correlated to a timestamp of 0 but has shifted to a different timestamp by the amount of the offset.

If you're not authoring a date library, you should not be epoch shifting.

For more details about epoch shifting, watch this video clip from Greg Miller at CppCon 2015. The video is about time_t in C++, but the explanation and problems are identical. (For JavaScript folks, every time you hear Greg mention time_t, just think "Date object".)

Trying to make a "UTC Date"

var d = new Date();
var utcDate = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds()));

In this example, both d and utcDate are identical. The work to construct utcDate was redundant, because d is already in terms of UTC. Examining the output of toISOString, getTime, or valueOf functions will show identical values for both variables.

A similar approach seen is:

var d = new Date();
var utcDate = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());

This is approach passes UTC values into the Date constructor where local time values are expected. The resulting Date object now represents a completely different point in time. It is essentially the same result as epoch shifting described earlier, and thus should be avoided.

The correct way to get a UTC-based Date object is simply new Date(). If you need a string representation that is in UTC, then use new Date().toISOString().

16
  • 1
    When you do this in the Firebug console: var date_time = new Date(), the value of date_time is (for me in AEST) Date {Sun Aug 21 2016 22:18:47 GMT+1000 (AEST)} and so therefore it seems it has stored a timezone. How can I ensure date_time is purely the UTC time, without any timezone included? Commented Aug 21, 2016 at 12:22
  • 9
    @user1063287—the toString method uses the host timezone offset to produce a date and time in the "local" time zone. The date object itself has a time value that is an offset from 1970-01-01T00:00:00Z, so effectively UTC. To see the UTC date and time, use toISOString.
    – RobG
    Commented Aug 23, 2016 at 22:47
  • 1
    @redcalx - that is a Rhino specific implementation, but even then, if you scroll to the very bottom you'll see that private double date is the only instance field. Everything else is static, and primarily there for caching environment provided values. It's not something tracked per-instance, or something you can modify easily. Commented Sep 20, 2016 at 19:01
  • 1
    The Date.UTC function is computing the timestamp based on UTC inputs is all. The output of .toString() will be the local time equivalent, and will show the local time zone offset, name, or abbreviation. Commented Sep 20, 2016 at 22:53
  • 1
    @redcalx— toString is implementation dependent and may or may not show the time zone in any particular format. Most browsers only return names or abbreviations for common time zones and the UTC offset for others.
    – RobG
    Commented Dec 6, 2016 at 4:35
234

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()}`);

18
  • 12
    I'm wondering why this answer isn't getting more love. For my purposes it is absolutely the best solution. In my app, all dates are UTC, but they need to be input or output in explicit IANA timezones in the UI. For this purpose I use this solution and it works perfectly. Simple, effective, standard.
    – logidelic
    Commented Feb 11, 2019 at 13:55
  • 4
    @logidelic it is a pretty new post. to be honest, i amazed myself when it struck me you could use toLocaleString to achieve the reverse effect, and yes, this should be common knowledge ! go write an article about it and mention me :-)
    – commonpike
    Commented Feb 11, 2019 at 14:36
  • 2
    For a node environment that is not in GMT already, the above code needs to change from var invdate = new Date(date.toLocaleString('en-US', { timeZone: ianatz })); into var invdate = new Date(${date.toLocaleString('en-US', { timeZone: ianatz })} GMT`);
    – Mike P.
    Commented May 29, 2019 at 20:28
  • 7
    Browsers are not required to parse the output of toLocaleString, so it's based on a faulty premise.
    – RobG
    Commented Sep 8, 2019 at 6:41
  • 37
    "...why this answer isn't getting more love?" - because the Date object it returns is a lie. Even the example shown, the string output includes the local machine's time zone. On my computer, both results say "GMT-0700 (Pacific Daylight Time)", where that is only correct for the first one (Toronto is actually in Eastern Time.) Beyond just the string output, the timestamp held within the Date object has been shifted to a different point in time. This can be a useful technique, but comes with a lot of caveats - primarily that Date object functions will not have normal output. Commented Apr 13, 2020 at 20:48
81

This should solve your problem, please feel free to offer fixes. This method will account also for daylight saving time for the given date.

dateWithTimeZone = (timeZone, year, month, day, hour, minute, second) => {
  let date = new Date(Date.UTC(year, month, day, hour, minute, second));

  let utcDate = new Date(date.toLocaleString('en-US', { timeZone: "UTC" }));
  let tzDate = new Date(date.toLocaleString('en-US', { timeZone: timeZone }));
  let offset = utcDate.getTime() - tzDate.getTime();

  date.setTime( date.getTime() + offset );

  return date;
};

How to use with timezone and local time:

dateWithTimeZone("America/Los_Angeles",2019,8,8,0,0,0)
11
  • This solution was fit for my need. I wasn't sure how exactly I can account for daylight saving.
    – hossein
    Commented Oct 7, 2019 at 9:08
  • 1
    Works perfectly fine in a Node js server! (Parse cloud code) Commented Oct 7, 2020 at 2:23
  • 6
    This is a bad idea as the format of toLocaleString is not specified, and the built–in parser is not required to parse it, especially when options have been included. Further, it may produce unreliable results in areas that observe daylight saving where the date and time to be parsed either doesn't exist (going into DST) or exists twice (goint out of DST), where implementations must make a choice as how to resolve those issues.
    – RobG
    Commented Aug 12, 2021 at 0:42
  • 1
    @Aidin—the formatMatcher method isn't relevant to the answer as only one language is supplied. The built–in parser is not required to parse any timestamp generated by toLocaleString. DST issues may or may not throw an error, and two different implementations may or may not produce different results. It also assumes a conversion from timezone offset abbreviation based on common names like ET (which are not standardised and are ambiguous) to IANA representative location like "America/Los_Angeles".
    – RobG
    Commented Nov 14, 2021 at 20:31
  • 1
    This produces incorrect datetimes for several hours surrounding daylight saving times if the computer running the code is in a zone that doesn't obey the same daylight saving shifts as the target zone. Confirm this by setting TZ=US/Arizona before launching node or in a browser with system time in US/Arizona. Then try the following example: dateWithTimeZone('America/Los_Angeles',2023,2,12,6,0,0).toISOString() produces 2023-03-12T14:00:00.000Z which is incorrect; it should be 2023-03-12T13:00:00.000Z. This time does not fall in the ambiguous Spring forward range 02:00 <= t < 03:00.
    – MDMower
    Commented Dec 16, 2023 at 20:08
57

You can specify a time zone offset on new Date(), for example:

new Date('Feb 28 2013 19:00:00 EST')

or

new Date('Feb 28 2013 19:00:00 GMT-0500')

Since Date store UTC time ( i.e. getTime returns in UTC ), javascript will them convert the time into UTC, and when you call things like toString javascript will convert the UTC time into browser's local timezone and return the string in local timezone, i.e. If I'm using UTC+8:

> new Date('Feb 28 2013 19:00:00 GMT-0500').toString()
< "Fri Mar 01 2013 08:00:00 GMT+0800 (CST)"

Also you can use normal getHours/Minute/Second method:

> new Date('Feb 28 2013 19:00:00 GMT-0500').getHours()
< 8

( This 8 means after the time is converted into my local time - UTC+8, the hours number is 8. )

3
  • 36
    Parsing any format other than ISO 8601 extended format is implementation dependant and should not be relied on. There is no standard for timezone abbreviations, e.g. "EST" might represent any one of 3 different zones.
    – RobG
    Commented Dec 6, 2016 at 4:36
  • 2
    The examples in this comment often do not work in internet explorer. As mentioned in the previous comment to this post, ISO 8601 is important. I confirmed by reading the ECMA-262 (Javascript 5th) edition language Specification.
    – Dakusan
    Commented Sep 7, 2017 at 23:24
  • This implementation is not time zone aware Commented Feb 7 at 22:01
23

It's now 2023, this question is 10 years old, with 1.1m views, but I was unhappy with all of the above solutions.

The original question was:

[if] I have "Feb 28 2013 7:00 PM ET", then [...] as far as I know, I can either set the UTC time or local time. But, how do I set time in another timezone?

  • Matt Johnson-Pint's answer was excellent, and almost was enough, but it stopped short of directly answering the question. The answer demonstrates setting a date in another time zone, but does so using the UTC offset (+08:00) rather than by timezone name as per the original question.
    • This points us to the "right" solution: specifying the UTC offset when we create the date; we just need to convert from the IANA time zone to UTC offset
  • commonpike's answer and chicken's answer both re-parse the locale-specific format, which is not standard Javascript and Mozilla advises against
    • They both also create a Date object that doesn't actually represent the desired UTC date and time
  • maowtm's answer was also almost right, but again it doesn't use the only format supported in the Javascript specification.
  • The other answers all suffer from the errors/bugs that Matt Johnson-Pint pointed out, and/or re-parsing non-standard formats.

The "right" way in 2023

Modern browsers and node.js>=18 give a list of ~400 time zones with the following query:

const tzs = Intl.supportedValuesOf("timeZone"); // [ "Africa/Abidjan", "Africa/Accra" ...]
console.log(tzs);

For each listed timezone we can get a GMT/UTC offset by constructing a DateTimeFormat instance, formatting a new date with the longOffset formatter, and parsing the result:

// gives '2/28/2013, GMT-05:00'
const tzname = "America/Detroit";
const longOffsetFormatter = new Intl.DateTimeFormat("en-US", {timeZone: tzname ,timeZoneName: "longOffset"});
const longOffsetString = longOffsetFormatter.format(new Date("2013-02-28T19:00:00.000")); // '2/28/2013, GMT-05:00'

// longOffsetString.split('GMT')[1] will give us '-05:00'
const gmtOffset = longOffsetString.split('GMT')[1];

console.log(longOffsetString);
console.log(gmtOffset);

Now we can construct a new Date, properly (i.e. internally it will have the correct UTC date/time), using the timezone offset string.

// Feb 28 2013 7:00 PM EST
const gmtOffset = '-05:00'; // see above to figure out where this came from
const d = new Date("2013-02-28T19:00:00.000" + gmtOffset);

console.log(d.toISOString()); // '2013-03-01T00:00:00.000Z' (UTC)
console.log(d.toLocaleString("en-US", {timeZone: "America/Detroit"})); // '2/28/2013, 7:00:00 PM'

4
  • 1
    Excellant work! I don't know why the browser makes it so hard to get the UTC offset from a timezone name, you have to do a dance of creating a datetime then throwing away the date. Commented Jan 7 at 15:15
  • 1
    One thing to be mindful of: the date-time used as input for computing "longOffsetString" will be interpreted as local time. This is a problem if you want to convert a date-time near Daylight Savings, for a different timezone than the one you're in. E.g. Input: March 10th, 2024, 06:30, local New York time Your local timezone: Europe/Athens (GMT+02:00) The correct offset is GMT-04:00, since daylight savings had already happened in NY on March 10th, 2024, at 02:00. Instead you get an offset of GMT-05:00 because "2024-03-10T06:30:00.000" is considered to be in your local time (GMT+02:00)
    – tudorturcu
    Commented Apr 18 at 15:04
  • 1
    @tudorturcu you're correct, but there's a bit more to it. The Date used as input for computing longOffsetString is a representation of a moment in time (internally it's milliseconds since 1970-01-01T00:00:00.000Z). The string given to the Date constructor is interpreted in exactly the same way as per Date.parse(). Date.parse() does, as you point out, use local time (if you provide a time but omit the timezone). So it's best to specify your desired moment in time in UTC, and provide a "Z" suffix to the string. The problem: at that point, we don't yet know the UTC offset!
    – cobberboy
    Commented Apr 19 at 14:40
  • Yes, precisely, it made complete sense why you wrote it like that, you can't specify the offset, that's what you're trying to compute. I was just wondering how to solve this if you need accurate time near Daylight Savings, but I didn't find an easy solution without using a library.
    – tudorturcu
    Commented Apr 20 at 22:31
10

I found the most supported way to do this, without worrying about a third party library, was by using getTimezoneOffset to calculate the appropriate timestamp, or update the time then use the normal methods to get the necessary date and time.

var mydate = new Date();
mydate.setFullYear(2013);
mydate.setMonth(02);
mydate.setDate(28);
mydate.setHours(7);
mydate.setMinutes(00);

// ET timezone offset in hours.
var timezone = -5;
// Approximate check for daylight savings if applicable (northern hemisphere)
var startDate = new Date(mydate.getFullYear(), 02, 31);
var endDate = new Date(mydate.getFullYear(), 09, 31);
var is_daylight_savings = mydate.getTime() >= startDate.getTime() && mydate.getTime() <= endDate.getTime();
if (is_daylight_savings) {
    timezone += 1;
}
// Timezone offset in minutes + the desired offset in minutes, converted to ms.
// This offset should be the same for ALL date calculations, so you should only need to calculate it once.
var offset = (mydate.getTimezoneOffset() + (timezone * 60)) * 60 * 1000;

// Use the timestamp and offset as necessary to calculate min/sec etc, i.e. for countdowns.
var timestamp = mydate.getTime() + offset,
    seconds = Math.floor(timestamp / 1000) % 60,
    minutes = Math.floor(timestamp / 1000 / 60) % 60,
    hours   = Math.floor(timestamp / 1000 / 60 / 60);

// Or update the timestamp to reflect the timezone offset.
mydate.setTime(mydate.getTime() + offset);
// Then Output dates and times using the normal methods.
var date = mydate.getDate(),
    hour = mydate.getHours();

EDIT

I was previously using UTC methods when performing the date transformations, which was incorrect. With adding the offset to the time, using the local get functions will return the desired results.

4
  • Where you calculated timezone_offset? Commented Mar 12, 2019 at 0:02
  • 1
    Oops, I mislabeled one of my variables. timezone_offset should have been offset, or visa versa. I've edited my answer to to show the correct variable name. Commented Apr 11, 2019 at 1:11
  • This answer will not work for time zones where daylight savings are used - e.g. the UK is GMT +00:00 for half the year, then becomes BST +01:00 for the other half.
    – BadHorsie
    Commented Jun 11 at 15:49
  • All you need to do to account for daylight savings is to increase your timezone by 1. I've edited the answer to include a check for dates within the northern hemisphere. If you're in the southern hemisphere instead, then you change it from is_daylight_savings to is_not_daylight_savings and increment your timezone value by 1 if is_not_daylight_savings is false. Commented Jun 13 at 3:04
5

For Ionic users, I had hell with this because .toISOString() has to be used with the html template.

This will grab the current date, but of course can be added to previous answers for a selected date.

I got it fixed using this:

date = new Date();
public currentDate: any = new Date(this.date.getTime() - this.date.getTimezoneOffset()*60000).toISOString();

The *60000 is indicating the UTC -6 which is CST so whatever TimeZone is needed, the number and difference can be changed.

3
  • @RichardVergis The question clearly states the user wants to change to local time, but doesn't state which time zone they're in. I stated my time zone as an example and the user can clearly read based off my example, they can input their time zone offset. Commented Apr 29, 2020 at 13:07
  • This is definitely working, However, I would be more interested in knowing how exactly. I know new Date().getTime() returns the current time in milliseconds but I don't get what the getTimezoneOffset() is at all. I have tried logging in to the console I can see it is -60 for me what does that mean really? Commented Oct 9, 2022 at 9:19
  • @AdeyanjuSegunSamuel check the docs. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…. Commented Oct 10, 2022 at 2:20
5

I ran into this issue running a GCP Cloud Function. Of course it works on a local machine, but running in the cloud makes the OS default (local) for new Date() irrelevant. In my case, an api call from the cloud required Eastern Standard Time, in ISO format (without the "Z") with offset as "-0500" or "-0400" depending on DST, for example:

2021-12-01T00:00:00.000-0500

Again, this is not a browser formatting issue, so I am forced into this format for the api call to work correctly.

Using @chickens code as a start, this is what worked:

var date = new Date(); 
var now_utc =  Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),
date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());

var dt = new Date(now_utc);

let utcDate = new Date(dt.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(dt.toLocaleString('en-US', { timeZone: "America/New_York" }));
let offset1 = utcDate.getTime() - tzDate.getTime();
let offset2 = offset1/60000;
let o1 = Math.abs(offset2);
console.log(offset2)
var offsetValue1 =  (offset2 < 0 ? "+" : "-") + ("00" + Math.floor(o1 / 60)).slice(-2) + ("00" + (o1 % 60)).slice(-2);
console.log(offsetValue1)
dt.setTime(dt.getTime() - offset1);

console.log(dt.toISOString());
console.log(dt.toISOString().slice(0,-1)+offsetValue1);
4

I ran into a similar problem with unit tests (specifically in jest when the unit tests run locally to create the snapshots and then the CI server runs in (potentially) a different timezone causing the snapshot comparison to fail). I mocked our Date and some of the supporting methods like so:

describe('...', () => {
  let originalDate;

  beforeEach(() => {
    originalDate = Date;
    Date = jest.fn(
      (d) => {
        let newD;
        if (d) {
          newD = (new originalDate(d));
        } else {
          newD = (new originalDate('2017-05-29T10:00:00z'));
        }
        newD.toLocaleString = () => {
          return (new originalDate(newD.valueOf())).toLocaleString("en-US", {timeZone: "America/New_York"});
        };
        newD.toLocaleDateString = () => {
          return (new originalDate(newD.valueOf())).toLocaleDateString("en-US", {timeZone: "America/New_York"});
        };
        newD.toLocaleTimeString = () => {
          return (new originalDate(newD.valueOf())).toLocaleTimeString("en-US", {timeZone: "America/New_York"});
        };
        return newD;
      }
    );
    Date.now = () => { return (Date()); };
  });

  afterEach(() => {
    Date = originalDate;
  });

});
3

I had the same problem but we can use the time zone we want
we use .toLocaleDateString()

eg:

var day=new Date();
const options= {day:'numeric', month:'long', year:"numeric", timeZone:"Asia/Kolkata"};
const today=day.toLocaleDateString("en-IN", options);
console.log(today);

1
  • 3
    The OP wants to parse a timestamp as if it was in a particular timezone, not generate a timestamp for a particular timezone, i.e. the opposite of what this answer does. They want to do something like "What is the time here when it was 10:30 am in Kolkata".
    – RobG
    Commented Aug 12, 2021 at 0:45
2

Building on the answers above, I am using this native one liner to convert the long timezone string to the three letter string:

var longTz = 'America/Los_Angeles';
var shortTz = new Date().
    toLocaleString("en", {timeZoneName: "short", timeZone: longTz}).
    split(' ').
    pop();

This will give PDT or PST depending on the date provided. In my particular use case, developing on Salesforce (Aura/Lightning), we are able to get the user timezone in the long format from the backend.

3
  • 1
    Just because I like to play pedant from time to time, 'America/Los_Angeles' is not a timezone, it's a "representative location" for a particular offset and daylight saving rules and the history of those changes (per the IANA time zone database). ;-)
    – RobG
    Commented Sep 23, 2019 at 13:20
  • Haha, you have to post that comment on multiple answers here :P
    – Shanerk
    Commented Sep 23, 2019 at 14:15
  • Yep. :-) BTW, not all timezone abbreviations are 3 letters, there are many with 4 such as ChST, AEST, AEDT, etc. and timeZoneName: "short" doesn't guarantee an abbreviation, sometimes it produces an offset like "GMT+10" depending on various factors. I think it's more reliable to use toString and get the part at the end between brackets, but still not 100%. :-(
    – RobG
    Commented Aug 12, 2021 at 0:49
2

I'm not sure why all these answers are so complicated. Just use YYYY-MM-DD ZZZ when creating a date-only date in the local / desired time zone.

Create a local date:

var myDate = new Date('2022-11-29 CST')

The date will be stored in storage as UTC, great.

Get the date out of storage and display it as local:

myDate.toLocaleDateString()

11/29/2022

3
  • Where do you get the three letter codes from? Is there some documentation on which codes we can use and what they mean?
    – Vincent
    Commented Nov 1, 2023 at 19:58
  • And what if you don't know whether it was CST or CDT on the date and time you're interested in?
    – tremby
    Commented Feb 26 at 7:02
  • @Shanerk 's answer can give you the CST/CDT etc code. I'm just testing this idea now Commented Jul 19 at 7:43
1

Try: date-from-timezone, it resolves expected date with help of natively available Intl.DateTimeFormat.

I used that method in one of my projects for few years already, but it's now I decided to publish it as small OS project :)

1

Try using ctoc from npm. https://www.npmjs.com/package/ctoc_timezone

It has got simple functionality to change timezones (most timezones around 400) and all custom formats u want it to display.

1

Thanks to @commonpike answer, I wrote a function which takes an ISO String date such as 2020-10-10T08:00:00.000 as input and send an object which contains 2 main properties.

The first one is fromUtc is a Date corresponding to the timeZone entered as parameter.

The second one is toUtc which lets you to format a Date stemming from fromUtc.

const timeZoneTransformer = (stringDate, timeZone = "Europe/Paris") => {
  const now = new Date();
  const serverDate = new Date(stringDate);
  const utcDate = new Date(
    Date.UTC(
      serverDate.getFullYear(),
      serverDate.getMonth(),
      serverDate.getDate(),
      serverDate.getHours(),
      serverDate.getMinutes(),
      serverDate.getSeconds()
    )
  );
  const invdate = new Date(
    serverDate.toLocaleString("en-US", {
      timeZone,
    })
  );
  const diff = now.getTime() - invdate.getTime();
  const adjustedDate = new Date(now.getTime() - diff);
  return {
    toUtc: utcDate,
    fromUtc: adjustedDate,
  };
};
const fromUtc = timeZoneTransformer("2020-10-10T08:00:00.000").fromUtc;
console.log(fromUtc);
const toUtc = timeZoneTransformer(fromUtc).toUtc;
console.log(toUtc);

0

I know its 3 years too late, but maybe it can help someone else because I haven't found anything like that except for the moment-timezone library, which is not exactly the same as what he's asking for here.

I've done something similar for german timezone, this is a little complex because of daylight saving time and leap years where you have 366 days.

it might need a little work with the "isDaylightSavingTimeInGermany" function while different timezones change on different times the daylight saving time.

anyway, check out this page: https://github.com/zerkotin/german-timezone-converter/wiki

the main methods are: convertLocalDateToGermanTimezone convertGermanDateToLocalTimezone

I've put an effort into documenting it, so it won't be so confusing.

1
  • 1
    This should be a comment, it's not an answer.
    – RobG
    Commented Nov 14, 2019 at 20:40
0

Try something like this,

public static getTimezoneOffset(timeZone: string, date = new Date()): number {
    const localDate = date.toLocaleString('fr', { timeZone, timeZoneName: 'long' });
    const tz = localDate.split(' ');
    const TZ = localDate.replace(tz[0], '').replace(tz[1], '').replace(' ', '');
    const dateString = date.toString();
    const offset = (Date.parse(`${dateString} UTC`) - Date.parse(`${dateString}${TZ}`)) / (3600 * 1000);
    return offset;
}
0

There are several working answers here, but somehow a lot of them seemed to get you to the string, but not back to a date object you started with, so here's my simple non-function take on how to change timezone on JS date:

var TZ='Australia/Brisbane'; //Target timezone from server
var date = new Date();       //Init this to a time if you don't want current time
date=new Date(Date.parse(date.toLocaleString("en-US", {timeZone: TZ})));
//Just a clarification on what happens
// 1) First new Date() gives you a Date object at current time in the clients browser local timezone
// 2) .toLocaleString takes that time, and returns a string if time in the target timezone
// 3) Date.parse converts that new string to a Unix epoch number
// 4) new Date() converts the Unix epoch into a Date object in the new TimeZone. 
// Now I can use my usual getHours and other Date functions as required.

Hope that helps others (if you get to this bottom answer!)

0

I had the same problem as OP which brought me to this thread and many others. None of the answers were able to "initialize a JavaScript Date to a particular time zone".

My scenario was a user selecting a date and a timezone (for a meeting), so whether in Unix time stamp, or UTC, etc, needed that dateTime to be in a given timezone, without knowing the offset from the users local time. Example user is in ? locale needs to set a meeting for 10:30 CST without knowing offset from local time. It's surprisingly difficult to set a certain date time from a different date time.

The following solution will instantiate a dateTime object in a non local timezone or converts a dateTime object to a different timezone, while maintaining the time it was originally set at. It is compliant with all modern browsers (and pretty decently far back), does not do anything questionable with browser apis, and takes in IANA date strings.

    const setDateInAnotherTimeZone=(inputDateTime, timeZone)=>{
    /**
     * This funciton will instantiate a dateTime object in a non local timezone 
     * or
     * Converts a dateTime object to a different timezone, while maintining the time
     * Parameters
     ** inputDateTime, a date object with the desired time and day selected (in the local/non-desired timezone)
     *** Example: new Date(2023, 10, 10, 10, 30) 10:30 (localalized to user timezone) on 10/30/2023
     ** timeZone, the desired timezone you want to set the date in.
     *** Example: var timeZone = 'US/Central' 
     *** Requires a 'tz database time zone' name aka an IANA timezone name
     *** Usefull list here https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
     *** Date.prototype.toLocaleString() usng IANA time zone names is widely supported
     *** https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString#browser_compatibility
     */
    console.log('desired Time Zone',timeZone) 
    console.log('desired Time     ', inputDateTime.toString().split(" ").slice(4,5).join(' ').toString()) 
    console.log('inputDateTime', inputDateTime) 
    
    const dateTZShifted = inputDateTime.toLocaleString("en-US", {timeZone : timeZone , dateStyle: 'long', timeStyle: 'long'})
    let timeTZShifted = dateTZShifted.split(" ").slice(4,5).join(' ').toString().split(':')
    var originalTime = inputDateTime.toString().split(" ").slice(4,5).join(' ').toString().split(':')
    let newLocalTime = [
        Number(originalTime[0]) - Number(timeTZShifted[0]) + Number(originalTime[0]) ,
        Number(originalTime[1]) - Number(timeTZShifted[1]) + Number(originalTime[1]) , 
        Number(originalTime[2]) -Number(timeTZShifted[2])  + Number(originalTime[2])
    ]
    let outputDate = new Date(inputDateTime)
    outputDate.setHours(Number(newLocalTime[0]), Number(newLocalTime[1]),Number(newLocalTime[2]))
    console.log('outputDateTime  ', outputDate.toLocaleString("en-US", {timeZone : timeZone , dateStyle: 'long', timeStyle: 'long'}) )
    return(outputDate)   
}
//Usage
let dateInAnotherTimeZone = setDateInAnotherTimeZone(new Date(2023, 7, 10, 10, 30),'US/Central')
let dateInAnotherTimeZone1 = setDateInAnotherTimeZone(DateObject,'America/New_York')

Expected Output

desired Time Zone US/Central

desired Time 10:30:00

inputDateTime

Thu Aug 10 2023 10:30:00 GMT-0400 (Eastern Daylight Time)

outputDateTime

August 10, 2023 at 10:30:00 AM CDT

or

Thu Aug 10 2023 11:30:00 GMT-0400 (Eastern Daylight Time)

0

If you are having problem with toISOString() try like this using 'UTC' in new Date() method:

 let start = new Date();
      let event = new Date(`${start} UTC`);
      event.setUTCHours(0, 0, 0, 0);
      console.log(event.toISOString()); //2023-10-30T00:00:00.000Z
0

Just like how @cobberboy felt in 2023, Same thoughts here and i tried one more approach, Using Intl.DateTimeFormat for setting up the timezone.

new Intl.DateTimeFormat('en-GB', {
    timeZone: 'America/Los_Angeles',
}).format(new Date())

This will convert the current local timezone date to the given timezone.

Using Other Attritbutes like dateStyle: 'full' and timeStyle: 'long' you can get the date and time. Along with that there are other attributes as well such as timeZoneName where instead of passing America/Los_Angeles you can pass other formats like PST

As the function returns string passing it to new Date instance will be easy and can to further processing on it if needed.

-1

Simple with Node.JS support

Pass in the amount of hours your timezone is offset from UTC

function initDateInTimezone(offsetHours) {
  const timezoneOffsetInMS = offsetHours * 60 * 60000;
  let d = new Date().getTimezoneOffset() * 60000 + timezoneOffsetInMS;
  const date = new Date(new Date().getTime() - d);
    return date
}
-4

Was facing the same issue, used this one

Console.log(Date.parse("Jun 13, 2018 10:50:39 GMT+1"));

It will return milliseconds to which u can check have +100 timzone intialize British time Hope it helps!!

1
  • 4
    (This post does not seem to provide a quality answer to the question. Please either edit your answer, or just post it as a comment to the question). Commented Jun 14, 2018 at 6:28
-4
//For Mumbai time difference is 5.5 hrs so
city_time_diff=5.5; //change according to your city

let time_now = Date.now();
time_now = time_now + (3600000 * city_time_diff); //Add our city time (in msec);
let new_date = new Date(time_now);
console.log("My city time is: ", new_date);

Not the answer you're looking for? Browse other questions tagged or ask your own question.