简体   繁体   中英

Why does an hour get added on to java.util.Date for dates before Nov 1 1971?

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)

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.

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.

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.

This is not a bug.

You have set your default timezone to BST which is (GMT + 1) , the GMT date of Jan 1 1970 00:00:00 , when you parse this date using BST timezone as your default, it always displays time based on your current timezone (auto applies offset from GMT ).

In this case it was GMT + 1 which is why your result was an hour off.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM