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

6

46

I have this backend that sends me a pre formatted time in a set time zone, but without any information for the said time zone. The strings are like: "2013-08-26 16:55:00".

I can create a new moment.js instance with this string:

var time = moment("2013-08-26 16:55:00") //this creates time in my tz

but this will only create an instance in my own time zone.

Moment.js have a plugin that can create instances of the object in specific time zones and it works great, but I can't say what time I want the object to point to.

If I'm in New York and I do this:

var time = moment("2013-08-26 16:55:00").tz("America/Los_Angeles");

the resulting time will be 13:55 instead of 16:55 but in LA.

What I want is to create an instance that will say 16:55, but in LA time.

The reason I'm asking is because I want to do this:

var now = moment.tz("America/Los_Angeles");
var end = moment("2013-08-26 16:55:00"); //plus something to convert LA time

var timeLeft = end.diff(now, "minutes");

Is there a way to do that?

Longinus answered 26/8, 2013 at 16:8 Comment(0)
S
62

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")
Subvert answered 26/8, 2013 at 17:11 Comment(4)
how do I do it, if a specific format and a strict parsing needs to be used as well?Heighten
@Heighten - Updated the answer to explain. Thanks.Subvert
@MattJohnson how does this work say for ex for 'America/New_York' ? seems like it just captures the browser's timezoneHalmstad
@andi - moment.js works with the browser's time zone by default and supports UTC. moment-timezone adds support for named IANA time zones, like America/New_York.Subvert
M
8

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/

Mickeymicki answered 5/3, 2017 at 7:50 Comment(2)
I would like to add that though this will work it is not recommended. It's best to default to UTC time as well as store time in UTC and convert to local time for users based on their timezone whenever necessary. It will save you from many headaches—not all, since timezones are insanely confusing.Mickeymicki
How to convert UTC time To timezone specific date, when i try to convert it is getting decresed to -1 or +1 ?Waits
C
2

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")

Course answered 23/5, 2020 at 10:56 Comment(0)
C
2

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

Cyprinoid answered 3/2, 2021 at 21:32 Comment(0)
D
1

I had a similar issue for which i had to use New York based time so i had to consider for daylight savings. I tried using the above few answers but wasn't able to get it working. Then I solved my issue like the below code

import moment from 'moment-timezone'

const time = timestamp
const offset = moment.tz.zone('America/New_York')?.parse(time)
const date = moment(time).add(offset, 'minutes').toISOString()

or you can do this way which will consider the time offset on its own when you display locally.

const time = moment.tz(timestamp, 'America/New_York')
const localtz = moment.tz.guess()
const date = time.clone().tz(localtz)

this gives you an ISO string which you can use as below

moment(date).local().format('dddd, MMM DD YYYY, hh:mm A')

or in whatever format you would like to display it

Dolabriform answered 1/9, 2020 at 10:59 Comment(4)
Hi your answer works partially for me ,how to know whether to add or minus the offset based on timezone , if we change the timezone will it gives the offset in negative ?Waits
@Waits i added a second method. It should give you positive or negative offsets so you only need to add itDolabriform
Thanks , here I have input in UTC string format , when i tried converting it is getting reduced to -1. how to convert UTC time to time zone specific date?Waits
@Waits did you double check your input date/your system timezone? if it is incorrect then you can add an hour to the initial moment as add(1, 'hour'). It happens that some api don't have a correct utc time or their utc time is actually their local timeDolabriform
C
0

You can set the moment's timezone during initializations without using .tz() function directly, like next:

        moment = include();
        const someMomentObj= moment();
        const someOtherMomentObj = moment();
        const yourTimezone = 'Africa/Accra';
        const momentObj = moment(
            `${someMomentObj.format('YYYY-MM-DD')} ${someOtherMomentObj} ${yourTimezone}`,
            'YYYY-MM-DD HH:mm z'
        );

In this case 'yourTimezone' constant will correspond to 'z' symbol of 'YYYY-MM-DD HH:mm z' input template. In same time you will not change initialized object's timezone, but just properly parse it as a input value.

Cryology answered 26/4, 2023 at 15:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.