tags:

views:

341

answers:

3

The following code appears to demonstrate a bug in java.util.Date whereby an hour gets added on if the local clock is set to GMT with DST adjustment on and the time is before Nov 1 1971. My first assumption is always that I've got it wrong. Can anyone see what's wrong (or is this really a Java bug)? What's significant about Nov 1 1971?

import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;

class JavaUtilDateBug
{
    private static void demo() throws Exception
    {
        // UK developers usually have the clock on their development machines set
        // to "Europe/London" (i.e. GMT with daylight saving). Set it explicitly 
        // here so readers in other countries can see the problem too.
        TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
        Locale.setDefault(Locale.ENGLISH);

        SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
        String strJan1st1970Expected = "Thu Jan 01 00:00:00 GMT 1970";
        String strJan1st1970Actual = dateFormat.parse(strJan1st1970Expected).toString();
        System.out.println("strJan1st1970Actual: " + strJan1st1970Actual); // -> "Thu Jan 01 01:00:00 GMT 1970"
        boolean jvmHasDateBug = !strJan1st1970Expected.equals(strJan1st1970Actual);
        System.out.println("jvmHasDateBug: " + jvmHasDateBug); // -> true

        // The anomaly only seems to affect times before 1 Nov 1971.
        final String strNov1st1971 = "Mon Nov 01 00:00:00 GMT 1971";
        assert strNov1st1971.equals(dateFormat.parse(strNov1st1971).toString());
    }

    public static void main(String[] args)
    {
        try
        {
            demo();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

My Java environment:

  java version "1.6.0_13"
  Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
  Java HotSpot(TM) Client VM (build 11.3-b02, mixed mode, sharing)
+11  A: 

It's the locale. From http://en.wikipedia.org/wiki/British_Summer_Time

the British Standard Time scheme was trialled between 27 October 1968 and 31 October 1971, when Britain remained on GMT+1 all year.

laalto
Wow, thought that'd have been too obscure to get answered twice...
Nick Holt
Bah. I had ma answer half done when I was notified of your two.
Michael Borgwardt
+15  A: 

There was a trial of British Standard Time between 27th Oct 1968 and 31st Oct 1971, which I suspect is what's causing this issue.

There's some details of the trial here:

http://en.wikipedia.org/wiki/British_Summer_Time#Single.2FDouble_Summer_Time

The timezone for Europe/London in Jan 1st 1970 was British Standard Time (GMT+1) so when you use a java.text.SimpleDateFormat to parse Jan 01 00:00:00 GMT 1970 it generates the correct epoch value equal to Jan 01 01:00:00 1970 in BST.

Then, due to the crappiness of java.util.Date, when you call java.util.Date.toString() it uses the default timezone for the current local as of now, which has changed to GMT and you get Jan 01 01:00:00 GMT 1970.

Nick Holt
Interesting. Still not clear why it's not symmetrical, though - if you feed in "Thu Jan 01 00:00:00 GMT 1970" you should get the same back.
David Easley
This is not a problem with java.util.Date's toString(), the behaviour is not different when you format it using the same SimpleDateFormat you used for parsing. See my answer for Sun's take on this.
Michael Borgwardt
Hey Michael - take a look at the normalize() method java.util.Date. It's called from the toString() method and makes the call TimeZone.getDefaultRef() to obtain the timezone. That looks like the cause right?
Nick Holt
That just gets the default time zone, which what David sets as the first thing in his script, and which is also used implicitly by SimpleDateFormat.
Michael Borgwardt
Interesting- didn't know that. Mind you I wasn't born then so I do have an excuse. :-)
RichardOD
@Michael - yeah, but isn't that the point, Date gets the default time zone as of now, which is GMT, while the date being returned from the SimpleDateFormat is correct in that it's 01:00 with time zone GMT+1.
Nick Holt
+3  A: 

I found a matching bug in Sun's bug database. Seems that they consider it a "historical inaccuracy" (the formatting apparently should produce "BST" as time zone rather than GMT - the hour would then be correct) and won't fix it, because deep down, the TimeZone implementation cannot handle places switching the name of their time zone.

As a workaround, you can explicitly set your time zone to GMT rather than "Europe/London". The problem then disappears.

Michael Borgwardt