2

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.

Community
  • 1
  • 1
Mauro
  • 861
  • 7
  • 8

1 Answers1

2

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Gaps, to my view, can have only one (non-exception throwing) way to handle them, namely "pretend the person forgot to adjust their watch" which is what Java seems to be doing in this case. But the part of problem here is that the Date constructors are not taking a TimeZone parameter, and they therefore operate in the local time zone... which makes resolving these dates even harder as, in effect, the local time zone changes during the switch-over. If they took a timezone parameter then there would be no ambiguity or gap... leaving just the leap seconds problem ;-) – Stephen Connolly Oct 24 '12 at 12:09
  • @StephenConnolly: No, there would still be an ambiguity/gap problem, assuming you were still expressing a local date/time *within* that time zone. The time zone itself does *not* change (e.g. I'm still in the Europe/London time zone whether that's observing BST or GMT). Gaps can be handled in various ways, too - it could return the final instant before the gap, the first instant after the gap, the "pretend the person forgot to adjust their watch" instant, or throw an exception. (Throwing an exception is definitely an option, IMO.) – Jon Skeet Oct 24 '12 at 12:29
  • I understand the three possibilities that you explained, but go back to 11pm should **never** happen, since there is **no** way to determine if February 15th 2013 11:00:00pm to 11:59:59pm is DST or not. And it is not a problem, because we have no "gap" at the end of DST. So, should I accept the answer that JS is just wrong? – Mauro Oct 24 '12 at 13:07
  • @Mauro: I'll rewrite the bit about the February part; 11pm would be ambiguous, but 12am wouldn't be. And yes, in this case it really, really looks like a JS bug. – Jon Skeet Oct 24 '12 at 13:31
  • @JonSkeet, no I was saying the the timezone should always be part of the constructor, as then specifying "BRT" or "BRST" would remove the issue... Of corse those 3/4letter codes are not unique... IST is also used by other countries and is not just "Irish Summer Time" – Stephen Connolly Oct 24 '12 at 17:05
  • @StephenConnolly: Those aren't time zones though. That's what I mean. They're "half time zones" (there isn't a good names far as I'm aware). They form a single time zone *together*. So specifying the time zone isn't enough. For example, when the clocks go back in the UK on October 28th, both 1.30am GMT and 1.30am BST are in the same time zone, which is Europe/London. So specifying the time zone *wouldn't* remove the ambiguity. – Jon Skeet Oct 24 '12 at 17:31
  • @JonSkeet depends on how you see it. GMT is a timezone that is valid all year long... That it is only British/Irish local time for half the year is a different issue... But perhaps GMT bias is blinding me – Stephen Connolly Oct 24 '12 at 20:04
  • @StephenConnolly: GMT is sort of a time zone, but one which isn't actually *used*. A time zone is meant to be a way of translating between fixed points in time and local time *in a specific place*. I think it would be a mistake to assume that "time zone" = "fixed offset from UTC with a name". That's certainly not what date/time APIs tend to treat as a time zone, and it's definitely not what Java does. So if `Date` had a `TimeZone` parameter, it most certainly wouldn't solve the problem. – Jon Skeet Oct 24 '12 at 20:53