How to create time in a specific time zone with moment.js

Solution 1:

In most cases, you can simply do this:

moment.tz("2013-08-26 16:55:00", "America/Los_Angeles")

If you require input other than ISO8601, then specify the format string as the second parameter, and the time zone as the third:

moment.tz("8/26/2013 4:55 pm", "M/D/YYYY h:mm a", "America/Los_Angeles")

And if you need to use moment's "strict parsing" mode, then that goes in the third parameter, and the time zone moves to the fourth position:

moment.tz("8/26/2013 4:55 pm", "M/D/YYYY h:mm a", true, "America/Los_Angeles")

Solution 2:

If you want to calculate everything in a specific timezone you want to set the default time zone using

A) moment.tz.setDefault("America/Los_Angeles");

For my use case (in a node.js project) I just set it right after requiring the moment modules like so:

let moment = require('moment');
require('moment-timezone');
moment.tz.setDefault("America/Los_Angeles");

All calls to moment() thereafter will create the time in the "America/Los_Angeles" setting, which is NOT the same as using:

B) moment.tz("2017-03-04 00:00", "America/Los_Angeles")

OR

C) moment("2017-03-04 00:00").tz("America/Los_Angeles")

both of which would create the moment object in UTC time (unless you already changed the default), and then convert it to be the Los Angeles timezone.

Running B or C above in the browser console yields:

_d: Fri Mar 03 2017 16:00:00 GMT-0800 (PST)
_i: "2017-3-4 00:00"

Notice _d shows March 3 4:00pm; this is because the moment object is created with March 4 12:00am in UTC time, then converted to Pacific timezone, which is 8 hours behind/the previous day.

source: http://momentjs.com/timezone/docs/#/using-timezones/default-timezone/

Solution 3:

install moment-timezone

> npm install moment-timezone

Or see https://momentjs.com/timezone/docs/

.tz(string, string)

moment.tz("2020-01-02 13:33:37", "Iran/Tehran")

Solution 4:

Just to make something abundantly clear, that is implied in other answers but not really stated:

  • You absolutely must either
    • use ISO8601 as your date format or
    • specify the format your string is in

.. when using the .tz(string datetime, [string format,] string zone) function, if you want moment to interpret the datetime argument you give to be in the zone you give. If you omit format, be sure to pass an ISO8601 formatted string


For 2 days I went round in circles, because my API was delivering a time string like "03 Feb 2021 15:00" and sure, it parsed OK, but it always used the timezone from my local machine, then converted to the timezone I gave:

//this always resulted in "2021-02-03 10:00 EST" if run on a machine in UTC
moment.tz("03 Feb 2021 15:00", "America/Indianapolis").format("YYYY-MM-DD HH:mm z")

This was massively confusing: the parsing was clearly working fine, because the date was right but the time was always wrong by however many hours there were between the machine and the given zone string

Switching to ISO format input worked:

//this always resulted in "2021-02-03 15:00 EST" if run on a machine in UTC
moment.tz("2021-02-03 15:00", "America/Indianapolis").format("YYYY-MM-DD HH:mm z")

As did declaring:

//this always resulted in "2021-02-03 15:00 EST" if run on a machine in UTC
moment.tz("03 Feb 2021 15:00", "DD MMM YYYY HH:mm", "America/Indianapolis").format("YYYY-MM-DD HH:mm z")

I hope this saves someone some time