1

My goal is to parse a date string with the format yyyy-MM-dd hh:mm:ss.SSS for a given timezone, using only Java 6 without any external libraries. My first approach was to configure a SimpleDateFormatter with a timezone. However, I'm not able to understand the results. Have a look at the following code:

List<String> zones = Arrays.asList("UTC", "CET", "Europe/London", "Europe/Berlin");

for(String zone: zones) {
  SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
  df.setTimeZone(TimeZone.getTimeZone(zone));
  Date result =  df.parse("1970-01-01 00:00:00.000");
  System.out.println(zone + ": " + result.getTime()); 
}

The output is as follows:

UTC: 0
CET: -3600000
Europe/London: -3600000
Europe/Berlin: -3600000

The first two results are as expected. In UTC, the unix epoch starts at exactly zero milliseconds, and there is a one hour difference to CET.

What I don't understand are the values for London and Berlin. Since the milliseconds for London equal the milliseconds for CET instead of UTC, I first assumed that daylight savings time is taken into account (since it's currently summer on the northern hemisphere and summertime in London is UTC+1, which equals CET). However, why is the value for Berlin the same? Shouldn't it be UTC+2 (or CET+1 if you want)?


My questions:

  • What's the explanation for the results? Is DST really taken into account?
  • Is there a better way for doing the conversion in Java 6?
ceran
  • 1,392
  • 1
  • 17
  • 43
  • 3
    London was in year-round DST at 1970-1-1 00:00:00 UTC. (Between 27 October 1968 and 31 October 1971, actually). As such, it had the same UTC offset as Berlin. – Andy Turner Aug 30 '17 at 17:45
  • 2
    CET is not a real time zone. You probably intended and got the “winter half” of the time zone that has CEST in summer. However, avoid those three and four letter abbreviations wherever you can. They are generally ambiguous and not standardized. And Java recognizes only a fraction of them, and sometimes interprets them in surprising ways. How the time zone you got, will understand a date in the summer half of the year, I dare not try to tell. – Ole V.V. Aug 30 '17 at 18:19
  • @OleV.V. yes, I thought it was *that* CET. Thanks for explaining. – ceran Aug 30 '17 at 19:17
  • @ceran, you’re welcome. To complicate matters further, I suspect that CET may be used about the time in several places that are currently on UTC+1 between October and March, but do not share historic time zone offset, making CET ambiguous when talking about dates in history. As a detail, CET may be short for “Central European Time” or just “Central Europe Time”, but without changing the meaning, fortunately. – Ole V.V. Aug 31 '17 at 07:37
  • 2
    I believe there’s a bug in your format pattern string: lowercase `hh` is for hour within AM or PM from 1 through 12, but you use it to match `00`, and you don’t have AM or PM in your date-time string. You probably intended `HH` for hour in day, from 0 through 23. Apparently the bug didn’t change your results. – Ole V.V. Aug 31 '17 at 07:42
  • 1
    An occasion to get on my soapbox. :-) This is what you too often get when you opt for Java 6 without any external libraries (like [ThreeTen Backport](http://www.threeten.org/threetenbp/)). It’s well known that `SimpleDateFormat` sometimes lets you get away with unnoticed bugs like this one, so when at some time in the future the bug surfaces, it will be cumbersome and expensive to trace it back to the wrong case used in the format pattern string. – Ole V.V. Aug 31 '17 at 07:49
  • @OleV.V.thanks for your comments and spotting that bug :) – ceran Aug 31 '17 at 15:09

1 Answers1

2

The results are correct, because that's the offsets used by London and Berlin in 1970 (both used +01:00).

It's not related to Daylight Saving Time, because nowadays it happens during March and October in these countries. Actually one could argue that London was in a "long" DST period, from 1968 to 1971, because the offset was +01:00 during this whole period.

It's just the nature of timezones: they're defined by governments and laws, and the respective politicians can change the offsets used by their countries for whatever reasons they have.

In the same links above, you can see that Berlin adopted DST only in 1980, and London changed the offset to zero (GMT) in 1971.


PS: as discussed in the comments, short names like CET are ambiguous and not standard (for lots of them, there's more than one timezone that uses the same abbreviation). Always prefer to use IANA timezones names (always in the format Region/City, like America/Sao_Paulo or Europe/Berlin).

Some names (such as CET) are recognized and set to arbitrary defaults - mainly due to retro-compatibility (or bad design) issues - but it's usually done in unexpected ways. Avoid such short names if you can: names like Europe/Berlin are much more clear and have no ambiguities.

  • 1
    Oh of course, thanks. for some reason I thought that the current offsets apply. – ceran Aug 30 '17 at 17:52
  • 1
    @ceran You're welcome! I'd say it's natural to think that offsets never change (I also did before learning all these timezone stuff). But unfortunately offsets can change at [anytime, anywhere](https://www.timeanddate.com/news/time). Just because one is used today, it doesn't mean it was always like that, and there's no guarantee that it'll be the same forever - I wish politicians weren't responsible for that. –  Aug 30 '17 at 17:58
  • One last question: when executing the code above for today's date, then there is one hour difference between UTC and London as well as between London and Berlin. However, the difference between UTC and CET is two hours. Why is that? – ceran Aug 30 '17 at 18:07
  • 1
    Both London and Berlin are currently in DST, so the current offset in London is `+01:00` and in Berlin is `+02:00`. And short names like `CET` are [ambiguous and not standard](https://stackoverflow.com/a/18407231/7605325) - these names are usually set to some arbitrary default (in this case, I believe it defaults to some central european timezone, which also has DST in August 2017, so it also uses `+02:00`) –  Aug 30 '17 at 18:14