momentjs: how to get the date in a specific timezo

2019-08-07 12:16发布

问题:

In a nutshell I want moment to respect server's timezone. I've set my machine's timezone to Alaska but I'm passing a Brisbane timezone string to moment. Now I need moment.toDate to return a date instance in the same timezone as the one I pass in the moment constructor; e.g.

m = moment("2016-11-20T08:00:00+10:00")
m.format() // "2016-11-20T08:00:00+10:00" 
m.toDate() // Sat Nov 19 2016 13:00:00 GMT-0900 (AKST) 

I want to get a Date instance from moment that's in the input timezone; e.g. somehow get toDate to return Sun Nov 20 2016 08:00:00 GMT+1000 (AEST).

FWIW I have tried the same code with and without moment.tz.setDefault and while it correctly changes the format result, toDate always uses the machine's timezone!

Update

The reason I need this behaviour is that some JavaScript libraries and controls don't understand moment and only work with Date and the time/date gets skewed when presented back by them. One example, the one I'm currently dealing with, is jQuery UI date picker control. I want the date picker to show the current date as it's on the server (or on a specific timezone).

Thanks in advance.

回答1:

The Date object represents the time in UTC internally, and can only use the time zone of the machine its running on when projected.

There's absolutely no way to produce a Date object that uses an arbitrary time zone. Any examples you may come across that try to manipulate the Date object (such by adding or subtracting time zone offsets) are fundamentally flawed.

Moment itself has great time zone support, including the moment-timezone extension for working with named time zones instead of just time zone offsets. But once you go back to a Date object - you're back at the mercy of the behavior of that object.

Sorry, but there's no way to achieve what you are asking. Perhaps you could elaborate as to why you wanted to do this, and I could recommend a workaround.


Update: With regards to your update, usually there is a mechanism for getting the value from a date picker as text, rather than as a date object. With the example of the jQuery UI date picker control, the onSelect event gives it to you as text already, or you can simply call .val() instead of .datepicker('getDate') to get the text out of the field. Once you have a textual value, you can then parse it with moment however you like.

Similarly, when setting the value, you don't necessarily need a Date object. You could just set the value of the textbox as a string, or you can pass a string to the setDate function.

In most cases, you won't have to go through a Date object. But if for some reason you do, then you'll need to artificially construct one with something crazy like:

var d = new Date(m.format('YYYY/MM/DD'));

Normally, I'd be against that - but if it's just there to get the pass a value to a UI control, then it's probably ok.



回答2:

This will get you a moment in the same timezone as the moment string, but toDate is always in the local timezone.

d = "2016-11-20T08:00:00+10:00"
m = moment(d).utcOffset(d)
m.format()
m.toDate()