Take my timezone as an example (AEST):

function parseDate(str_date) {
  return new Date(Date.parse(str_date));
}


var str_date = "2015-05-01T22:00:00+10:00"; //AEST time
var locale_date = parseDate(str_date);

locale_date: Fri May 01 2015 22:00:00 GMT+1000 (AEST)

var str_date = "2015-05-01T22:00:00+00:00" //UTC time
var locale_date = parseDate(str_date);

locale_date: Sat May 02 2015 08:00:00 GMT+1000 (AEST)

Answer from Leo on Stack Overflow
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Global_Objects › Date › parse
Date.parse() - JavaScript | MDN
The following call, which does not specify a time zone will be set to 2019-01-01 at 00:00:00 in the local timezone of the system, because it has both date and time. ... Apart from the standard date time string format, the toString() and toUTCString() formats are supported:
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Global_Objects › Date › toTimeString
Date.prototype.toTimeString() - JavaScript | MDN
const d = new Date(0); console.log(d.toString()); // "Thu Jan 01 1970 00:00:00 GMT+0000 (Coordinated Universal Time)" console.log(d.toTimeString()); // "00:00:00 GMT+0000 (Coordinated Universal Time)" ... This page was last modified on Jul 10, 2025 by MDN contributors.
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Global_Objects › Date › toLocaleTimeString
Date.prototype.toLocaleTimeString() - JavaScript | MDN
When the method is called many times with the same arguments, it is better to create an Intl.DateTimeFormat object and use its format() method, because a DateTimeFormat object remembers the arguments passed to it and may decide to cache a slice of the database, so future format calls can search for localization strings within a more constrained context. // Depending on timezone, your results will vary const event = new Date("August 19, 1975 23:15:30 GMT+00:00"); console.log(event.toLocaleTimeString("en-US")); // Expected output: "1:15:30 AM" console.log(event.toLocaleTimeString("it-IT")); // Expected output: "01:15:30" console.log(event.toLocaleTimeString("ar-EG")); // Expected output: "١٢:١٥:٣٠ ص"
🌐
Plain English
plainenglish.io › blog › how-to-initialize-a-javascript-date-to-a-particular-time-zone-a03969601c58
How to Initialize a JavaScript Date to a Particular Time Zone?
The JavaScrip date object has the toLocaleString method to convert a date to a date string in the given time zone. ... const d = new Date("2020-04-13T00:00:00.000+08:00"); const dateStr = d.toLocaleString('en-US', { timeZone: 'America/New_York' ...
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Global_Objects › Date › toISOString
Date.prototype.toISOString() - JavaScript | MDN
const event = new Date("05 October 2011 14:48 UTC"); console.log(event.toString()); // Expected output: "Wed Oct 05 2011 16:48:00 GMT+0200 (CEST)" // Note: your timezone may vary console.log(event.toISOString()); // Expected output: "2011-10-05T14:48:00.000Z" ... A string representing the given date in the date time string format according to universal time.
🌐
Go Make Things
gomakethings.com › getting-a-date-in-the-current-users-timezone-with-javascript
Getting a date in the current user's timezone with JavaScript | Go Make Things
Last week, a friend of mine nerd-sniped me into an interesting challenge. An API they’re using returns the date as a string in a fixed timezone (in their case, Denver, Colorado, USA), like this… let dateFromAPI = '2025-01-31T11:50:15'; And they wanted to display it as a formatted string in the current user’s local time.
🌐
Netlify
netlify.com › blog › how-to-get-timezone-in-javascript-with-edge-functions
How to get the user‘s timezone in JavaScript with Edge Functions
To adjust a date by timezone in JavaScript, you can use the Date object and its toLocaleString() method.
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Global_Objects › Date › toString
Date.prototype.toString() - JavaScript | MDN
Date.prototype.toString() returns a string representation of the Date as interpreted in the local timezone, containing both the date and the time — it joins the string representation specified in toDateString() and toTimeString() together, adding a space in between.
Find elsewhere
🌐
Twilio
twilio.com › blog › converting-formatting-dates-timezones-javascript
Converting and Formatting Dates and Time Zones with JavaScript
June 30, 2022 - To see this in action, delete the ... code: const now = new Date(); const formatter = new Intl.DateTimeFormat('en-US', { hour: 'numeric', hour12: false, minute: 'numeric', weekday: 'long', timeZone: 'Asia/Tokyo', }); console.log('Date ...
Top answer
1 of 16
969

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:

  • Luxon (successor of Moment.js)
  • date-fns-tz (extension for date-fns)
  • Day.js (when using its Timezone plugin)

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.

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().

2 of 16
250

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.

Consider the following function

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

}

However, closely looking at the return value, this can be simplified to:

function changeTimezone(date, ianatz) {
  return new Date(date.toLocaleString('en-US', {
    timeZone: ianatz
  }));
}

// E.g.
var here = new Date();
var there = changeTimezone(here, "America/Toronto");

console.log(`Here: ${here.toString()}\nToronto: ${there.toString()}`);

🌐
Reddit
reddit.com › r/learnjavascript › question regarding dates and time zones
r/learnjavascript on Reddit: Question regarding dates and time zones
August 10, 2023 -

We are trying to add times to our dates in an older app and the dates were almost always stored as partially formed ISO strings. Not a hard rule since times were never used before.

Now I need to start displaying the times with the dates and allowing the user to alter the times on the front end.

Example: we get a date ISO string from the backend as 2008-08-15T00:00:00.

When I create a Date object from it, I get the date in my local time zone (GMT-0600). In this example, Fri, August 15, 2008 00:00:00 (GMT-0600).

Then later when the edit form is submitted with no change to the day or time, I convert the Date object to an ISO string and strip the milliseconds and time zone code to keep it consistent with the current format in the database. In this example it returns 2008-08-15T06:00:00 to the backend.

Notice the time was provided as 00:00:00 but after parsing it and then converting to an ISO string, I've now added 6 hours to the time and am returning 06:00:00.

I am thinking I could convert it to GMT-0000 before converting to an ISO string but I'm not sure if that is the cleanest solution. Has anyone else had a similar scenario and what would you suggest to do to make this work (that doesn't include altering all the dates in the DB, we're planning for that down the road)?

Top answer
1 of 5
2
Had the same issue, our DB and servers are set to UTC but in browser they're set to user timezone, which JS always assumes. To ensure JS knows what timezone the time you're providing is in, append it to the end of your timestamp. For example: new Date(myTimestamp + " UTC"). Yep, looks horrific but is a valid and recommended solution apparently. Welcome to JavaScript! Also be sure to check Safari support as the wah Safari handles dates is very messed up.
2 of 5
2
new Date() defaults to using the local timezone pulled from the browser which is pulled from the OS. When dealing with times the best way to handle is to store dates in ISO or UTC, or if you want to store local times, store the IANA timezone string. ('America/Chicago' or 'America/Sao_Paulo') and always track the users locale string ('en-US', 'pt-BR) Then explicitly use both locale and IANA. So when you display on the frontend you can use something like this: new Date().toLocaleString( 'en-US', { dateStyle: 'medium', timeStyle: 'medium', timeZone: 'America/Chicago' } ) new Date() in the browser assumes UTC but toString converts to local. Give it a date without time new Date('2022-02-22') and it will convert FROM UTC TO your local standard time. The ASSUMPTION is this string comes from standard server time. date-fns and Luxon do the opposite. They assume '2022-02-22' is local time. parseISO('2022-02-22') without specifying timezone converts FROM local TO local. That's why they feel more intuitive if you're not paying attention. I HIGHLY encourage always using toLocaleString for formatting, even if you're using Luxon or date-fns. Don't give your users these manually formatted "MM/yyyy" things. Locale string formats are locale aware (sometimes dates go before moths), lowercase months when they're supposed to be lowercase, and handle translations. (Yeah! Translations!) So months days, weekdays, etc. will be translated. And for Spanish speaking countries they will use more standard things like 'de' which translates to 'of'. Aug 11, 2023, 2:32:00 PM 11 de ago. de 2023, 14:32:00
🌐
GitHub
github.com › date-fns › date-fns › issues › 2642
How to parse a date string as a specific time zone · Issue #2642 · date-fns/date-fns
September 22, 2021 - You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. ... There was an error while loading. Please reload this page. ... I cannot quite find the right function to build a UTC date object from a date string, the format of the date string and the TZ Database name that the date in the date string is in.
Author   hardysabs2
🌐
GeeksforGeeks
geeksforgeeks.org › javascript › how-to-convert-date-to-another-timezone-in-javascript
How to Convert Date to Another Timezone in JavaScript? - GeeksforGeeks
July 12, 2025 - let date = new Date(Date.UTC(2012, ... console.log('USA date: ', usaTime); ... The toLocaleString() method is used to return a string that formats the date according to the locale and options specified....
Top answer
1 of 2
2

I want to combine these strings into one datetime object like (2020-05-05T15:30:00-09:00)

Date objects are extremely simple, they're just a time value that is an offset in milliseconds since 1970-01-01T00:00:00Z, so are inherently UTC. The built–in parser is unreliable and lacks any functionality such as format tokens.

So if you have separate values like:

  • Date string (2020-05-05)
  • Time string (15:30)
  • Timezone offset (-09:00)

then you can create a string that is compliant with the format defined in ECMA-262 and that should be parsed correctly by the built–in parser, e.g.

new Date('2020-05-05T15:30:00.000-09:00')

However, general advice is to avoid the built–in parser due to differences in implementations. Also, the format must be exact (e.g. including seconds and milliseconds in the timestamp, colon (:) in the offset) or some implementations will reject it as malformed and return an invalid date.

Once you have a Date object, getting a "local" timestamp with offset is an issue of formatting, which has been answered many times before (e.g. How to format a JavaScript date). There aren't any decent built–in formatting functions (toLocaleString with options is OK for some purposes but generally lacking in functionality), so you'll have to either write your own function, or use a library.

The following examples use Luxon, which is suggested as the upgrade path from moment.js.

With Luxon, if you specify a representative location, you'll get the offset for that location at the date's date and time. Alternatively, you can fix the offset to a set value, essentially setting it for a timezone without a representative location, so it doesn't have any reference to daylight saving or historic offset changes:

let DateTime = luxon.DateTime;

// Offset per the specified location
let d0 = DateTime.fromISO('2020-01-01', {zone: 'America/Yakutat'});
let d1 = DateTime.fromISO('2020-06-30', {zone: 'America/Yakutat'});
console.log(d0.toString());
console.log(d1.toString());

// Fixed offset per the supplied string
let d2 = DateTime.fromISO('2020-05-05T15:30:00.000-09:00', { setZone: true});
let d3 = DateTime.fromISO('2020-01-01T15:30:00.000-09:00', { setZone: true});
console.log(d2.toString());
console.log(d3.toString());
  
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/global/luxon.min.js"></script>

2 of 2
1

I get 16:30 due to DST

A date before March or after October will give 15:30

let dateString = "2020-05-05"+"T"+"15:30"+":00"+"-09:00"
console.log(dateString)
const date = new Date(dateString)
console.log(date)
const Anchorage = date.toLocaleString('en-US', {timeZone: 'America/Anchorage', hour12: false})
console.log(Anchorage)

let options = {}
options.timeZone = 'America/Anchorage';
options.timeZoneName = 'short';
console.log(date.toLocaleDateString('en-US'), date.toLocaleTimeString('en-US', options));

🌐
Bobby Hadz
bobbyhadz.com › blog › javascript-convert-date-to-timezone
Convert a Date to another Time Zone using JavaScript | bobbyhadz
Use the toLocaleString() method to get a string that represents the date according to the provided time zone. Pass the result to the Date() constructor. The returned Date object will have its date and time set according to the provided time zone.
🌐
Full Stack Foundations
fullstackfoundations.com › blog › javascript date tutorial: get the timezone right!
JavaScript Date Tutorial: Get the Timezone Right!
March 29, 2024 - In this case, “Z” comes from ... Time” (military) === UTC time (JavaScript) Every time you use the toISOString() on a JavaScript Date object, you will ALWAYS get a UTC representation of the date, indicated by Z....
🌐
Ursahealth
ursahealth.com › new-insights › dates-and-timezones-in-javascript
Working with dates and timezones in JavaScript: a survival guide
May 4, 2021 - In these cases, the JavaScript Date object often supplies too much or erroneous information · So what’s going on here? The date you’re receiving from the server is a moment in time. It’s midnight of the timezone to which the server is set. Your code is probably localizing it per the timezone settings on the user’s computer.