简体   繁体   English

为什么要在1971年11月1日之前将一个小时加到java.util.Date上?

[英]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. 以下代码似乎演示了java.util.Date中的错误,如果将本地时钟设置为GMT且启用DST调整并且时间在1971年11月1日之前,则会增加一个小时。我的第一个假设始终是弄错了。 Can anyone see what's wrong (or is this really a Java bug)? 谁能看到哪里出了问题(或者这真的是Java错误)? What's significant about Nov 1 1971? 1971年11月1日有什么重要意义?

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环境:

  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. 1968年10月27日至1971年10月31日之间进行了英国标准时间的审判,我怀疑是造成此问题的原因。

There's some details of the trial here: 这里有一些审判的细节:

http://en.wikipedia.org/wiki/British_Summer_Time#Single.2FDouble_Summer_Time 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. 1970年1月1日在欧洲/伦敦的时区为英国标准时间(GMT + 1),因此当您使用java.text.SimpleDateFormat解析格林尼治标准时间1970年1月1日00:00:00时,它将生成等于1月01日的正确历元值1970年1月1日在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. 然后,由于java.util.Date的脆弱性,当您调用java.util.Date.toString()它使用的当前时区的默认时区为now现在已更改为GMT,您将获得Jan 01 01: 1970年格林尼治标准时间00:00。

It's the locale. 这是语言环境。 From http://en.wikipedia.org/wiki/British_Summer_Time 来自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. 英国标准时间计划在1968年10月27日至1971年10月31日之间进行了试用,当时英国整年都保持GMT + 1。

I found a matching bug in Sun's bug database. 我在Sun的错误数据库中找到了匹配的错误。 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. 似乎他们认为这是“历史错误”(格式显然应将“ BST”作为时区而不是GMT-时分将是正确的),并且将无法解决,因为从深处看,TimeZone实现无法处理位置切换其时区的名称。

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 ). 您已将默认时区设置为BST ,即(GMT + 1) ,即GMT日期Jan 1 1970 00:00:00 ,当您使用BST时区作为默认时区解析该日期时,它始终显示基于当前时区的时间(自动应用相对于GMT偏移量)。

In this case it was GMT + 1 which is why your result was an hour off. 在这种情况下, GMT + 1 ,这就是为什么您的成绩减少一个小时的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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