1º Day of Daylight Saving Time Java and JS showing

2019-07-20 22:15发布

问题:

Assuming Brasilia GMT -0300: DST on 21/10/2012 at 00:00:00, when the clock should be advanced by one hour

Java

new Date(2012 - 1900, 9, 21, 0, 0, 0)
Sun Oct 21 01:00:00 BRST 2012

Chrome/FireFox (console)

new Date(2012, 9, 21, 0, 0 ,0)
Sat Oct 20 2012 23:00:00 GMT-0300 (Hora oficial do Brasil)

The result in Java is what I was expecting, but the result in JS I can not understand. I found this post where bjornd says

This is an absolutely correct behavior

but didn't explain why this behavior is OK.

My question is:

Why JS is returning a date one hour in the past?

P.S. I know Date is marked for "deprecation", but I'm using GWT; Date is my only option.

回答1:

Basically, that answer was incorrect as far as I can see. I'm not entirely happy with the Java version, even.

Fundamentally, you're trying to construct a local date/time which never happened. Translating from local time to UTC is always tricky, as there are three possibilities:

  • Unambiguous mapping, which in most time zones is the case for all but two hours per year
  • Ambiguous mapping, during a backward transition, where the same local time period occurs twice (e.g. local time goes 12:59am, 1am, ... 1:59am, 1am, 1:59am, 2am)
  • "Gap" mapping, where a local time period simply doesn't exist (e.g. local time goes 12:59am, 2am, 2:01am)

Brazil moves its clocks forward at midnight, so local time actually goes:

October 20th 11:58pm
October 20th 11:59pm
October 21st 01:00am
October 21st 01:01am

The local time you've asked for simply never happened. It looks like Java is just assuming you want to roll it forward... whereas JavaScript is getting confused :( The JavaScript result would be more understandable (but still incorrect) if you were asking for midnight at the start of February 16th 2013, for example - where the clocks would have gone back to 11pm on the 15th. 12am on the 16th is unambiguous, as it can only happen after the "second" 11pm-11:59pm on the 15th.

A good date/time API (in my very biased view) would force you to say how you want to happen ambiguity and gaps when you do the conversion.