ChatGPT解决这个技术问题 Extra ChatGPT

Format date in a specific timezone

I'm using Moment.js to parse and format dates in my web app. As part of a JSON object, my backend server sends dates as a number of milliseconds from the UTC epoch (Unix offset).

Parsing dates in a specific timezone is easy -- just append the RFC 822 timezone identifier to the end of the string before parsing:

// response varies according to your timezone const m1 = moment('3/11/2012 13:00').utc().format("MM/DD HH:mm") // problem solved, always "03/11 17:00" const m2 = moment('3/11/2012 13:00 -0400').utc().format("MM/DD HH:mm") console.log({ m1, m2 })

But how do I format a date in a specifc timezone?

I want consistent results regardless of the browser's current time, but I don't want to display dates in UTC.

Moment doesn't support this yet, but they're working on it. github.com/timrwood/moment/pull/671
This should just work. If you pass moment a time string that includes the desired offset, then it should retain that offset and display the local time as given, rather than automatically adjusting to browser-local time. If I wanted it to adjust to browser-local time, then I'd give it a UTC time instead of explicitly giving it an offset to use. I mean... I give it an explicit offset, why is it basically eating it up and doing it's own conversion to the browsers offset. Terrible design.
@Triynko offsets are subjected to daylight savings so, it doesn't always work as expected.
Something related to this, I want to print time in a specific format, e.g 15 March, 2018 but cant find the format string to do this. The generic DD MMM, YYYY does not work, when I use it like moment.tz("2018-02-15T14:20:00.000+0530", "Asia/Bangkok").format("DD MMM, YYYY"). Can someone point me in the documentation where I can find all the keys for formatting time when using this api.
@PramodKumar What's wrong? That gives "15 Feb, 2018". Did you mean to use format string DD MMMM, YYYY to get "15 February, 2018"?

C
Community

As pointed out in Manto's answer, .utcOffset() is the preferred method as of Moment 2.9.0. This function uses the real offset from UTC, not the reverse offset (e.g., -240 for New York during DST). Offset strings like "+0400" work the same as before:

// always "2013-05-23 00:55"
moment(1369266934311).utcOffset(60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).utcOffset('+0100').format('YYYY-MM-DD HH:mm')

The older .zone() as a setter was deprecated in Moment.js 2.9.0. It accepted a string containing a timezone identifier (e.g., "-0400" or "-04:00" for -4 hours) or a number representing minutes behind UTC (e.g., 240 for New York during DST).

// always "2013-05-23 00:55"
moment(1369266934311).zone(-60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).zone('+0100').format('YYYY-MM-DD HH:mm')

To work with named timezones instead of numeric offsets, include Moment Timezone and use .tz() instead:

// determines the correct offset for America/Phoenix at the given moment
// always "2013-05-22 16:55"
moment(1369266934311).tz('America/Phoenix').format('YYYY-MM-DD HH:mm')

@ebi It already uses the browser's timezone by default. To access the browser's timezone offset, use .zone() as a getter, which returns minutes from UTC (e.g., returns 300 for New York during standard time).
@EricCope No, not quite. You can use .tz("America/Phoenix") if you include momentjs.com/timezone as well, however. I've updated the answer with an example.
Note that using offset will not work as expected if the timezone have different offsets due to daylight savings.
Will .utcOffset() automaticly manage daylight saving times? like when i set UTC +1 CET in Winter will it bet UTC +2 CEST during Daylight saving time? Cause this makes it usable or not!
@haemse utcOffset() has nothing to do with DST or time zone rules. It just looks at the moment you've already constructed and gets/sets the number of minutes from UTC. Use the Moment Timezone library with a named timezone ("America/Phoenix") if you want to handle DST and other rules for known time zones.
N
Nicola Pedretti

A couple of answers already mention that moment-timezone is the way to go with named timezone. I just want to clarify something about this library that was pretty confusing to me. There is a difference between these two statements:

moment.tz(date, format, timezone)

moment(date, format).tz(timezone)

Assuming that a timezone is not specified in the date passed in:

The first code takes in the date and assumes the timezone is the one passed in. The second one will take date, assume the timezone from the browser and then change the time and timezone according to the timezone passed in.

Example:

moment.tz('2018-07-17 19:00:00', 'YYYY-MM-DD HH:mm:ss', 'UTC').format() // "2018-07-17T19:00:00Z"

moment('2018-07-17 19:00:00', 'YYYY-MM-DD HH:mm:ss').tz('UTC').format() // "2018-07-18T00:00:00Z"

My timezone is +5 from utc. So in the first case it does not change and it sets the date and time to have utc timezone.

In the second case, it assumes the date passed in is in -5, then turns it into UTC, and that's why it spits out the date "2018-07-18T00:00:00Z"

NOTE: The format parameter is really important. If omitted moment might fall back to the Date class which can unpredictable behaviors

Assuming the timezone is specified in the date passed in:

In this case they both behave equally

Even though now I understand why it works that way, I thought this was a pretty confusing feature and worth explaining.


moment(...).tz is not a function
Did you install moment-timezone?
is there a way to get the parsed and converted moment back without formatting? For example, if I want to format different ways without parsing it all over again.
P
Philip Nuzhnyy

Use moment-timezone

moment(date).tz('Europe/Berlin').format(format)

Before being able to access a particular timezone, you will need to load it like so (or using alternative methods described here)

moment.tz.add('Europe/Berlin|CET CEST CEMT|-10 -20 -30')

I don't think moment tz was available when the question was asked, but I do think this might be the way to go. I'm currently working on a similiar problem with all timestamps stored as UTC in MySQL, but to be viewed in a specific zone dependent on user config and not the timezone of the client.
M
Manto

.zone() has been deprecated, and you should use utcOffset instead:

// for a timezone that is +7 UTC hours
moment(1369266934311).utcOffset(420).format('YYYY-MM-DD HH:mm')

f
facundofarias

I was having the same issue with Moment.js. I've installed moment-timezone, but the issue wasn't resolved. Then, I did just what here it's exposed, set the timezone and it works like a charm:

moment(new Date({your_date})).zone("+08:00")

Thanks a lot!


You shouldn't use the new Date() constructor. Moment provides everything you'd ever need to parse dates. See Parsing docs.
Yes, but if I don't do that, I am receiving a warning from Moment, that it is deprecated of something like that
The warning means Moment is internally falling back to exactly what you're doing (using new Date() internally), but this is inconsistent across browsers. Instead, you should use provide the expected format as the second argument. Example: moment("12-25-1995", "MM-DD-YYYY").
B
Bard Rotzer

Just came acreoss this, and since I had the same issue, I'd just post the results I came up with

when parsing, you could update the offset (ie I am parsing a data (1.1.2014) and I only want the date, 1st Jan 2014. On GMT+1 I'd get 31.12.2013. So I offset the value first.

moment(moment.utc('1.1.2014').format());

Well, came in handy for me to support across timezones

B


C
Cosmin Staicu

If you pass the timestamp as the parameter to moment() (e.g if the timezone is Asia/Hong_kong which is +08:00), what I do is:

const localDateTime = moment((item.createdAt.seconds + 8 * 3600) * 1000).format('YYYY-MM-DD HH:mm:ss');

This is very dangerous, because named timezones like Asia/Hong Kong are NOT the same as a fixed offset 8 * 3600! Most timezones have daylight saving, so the offset changes throughout the year.
K
K.Karthik

You can Try this ,

Here you can get the date based on the Client Timezone (Browser).

moment(new Date().getTime()).zone(new Date().toString().match(/([-\+][0-9]+)\s/)[1]).format('YYYY-MM-DD HH:mm:ss')

The regex basically gets you the offset value.

Cheers!!


Usually, moment gives you everything you need. You never need to match anything custom.