代码之家  ›  专栏  ›  技术社区  ›  sergtk

用java.util.date类表示1921年5月1日午夜的问题

  •  3
  • sergtk  · 技术社区  · 15 年前

    我想用java.util.date类表示午夜。 为了检查这个,我输出这个值并获得意外的结果。

    代码如下:

    Calendar calendar = new GregorianCalendar(1921, 4, 1, 0, 0);
    Date date2 = calendar.getTime();
    System.out.println(date2);
    

    我得到以下输出:

    Sun May 01 00:20:08 EET 1921
    

    但我希望

    Sun May 01 00:00:00 EET 1921
    

    这种行为的原因是什么?

    目前我正在欧洲/赫尔辛基时区测试我的代码。

    4 回复  |  直到 15 年前
        1
  •  11
  •   jarnbjo    15 年前

    你为什么不简单地检查一下你国家的时区历史?几天前你也问过类似的问题。在1921年4月30日之前,芬兰的时区是非常奇怪的格林尼治标准时间+1:39:52。从5月1日起,他们改为格林尼治标准时间+2:00,从23:59:59跳到00:20:08。

        2
  •  3
  •   fvu    15 年前

    幸运的是,上一次我的测试代码仍然很方便;-)

    public static void main(String[] args) {
        Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("Europe/Helsinki"));
        calendar.set(1921,4, 1, 0, 0);
        Date date2 = calendar.getTime();
        System.out.println("GregorianCalendar: " + date2);
    
        DateTime c2 = new DateTime(DateTimeZone.forID("Europe/Helsinki")).withYear(1921).
                withMonthOfYear(5).withDayOfMonth(1).withHourOfDay(0). withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0);
        System.out.println("Joda: " + c2);
    }
    

    给予

    GregorianCalendar: Sat Apr 30 23:20:43 CEST 1921
    Exception in thread "main" org.joda.time.IllegalFieldValueException: Value 0 for minuteOfHour is not supported: Illegal instant due to time zone offset transition: 1921-05-01T00:00:35.781 (Europe/Helsinki)
        at org.joda.time.chrono.ZonedChronology$ZonedDateTimeField.set(ZonedChronology.java:469)
        at org.joda.time.DateTime.withMinuteOfHour(DateTime.java:1485)
    
        3
  •  1
  •   Peter Lawrey    15 年前

    实际上,很多时区在1979年10月之前就产生了奇怪的结果。 如果你想要准确的历史时区,我建议你看看Joda Time。

    出于某种原因,最糟糕的一天似乎是1900年1月1日。尝试

    Calendar calendar = new GregorianCalendar(1900, 1, 1, 0, 0);
    Date date2 = calendar.getTime();
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
    System.out.println("Time in UTC is " + date2);
    
    for (String tz : TimeZone.getAvailableIDs()) {
        TimeZone.setDefault(TimeZone.getTimeZone(tz));
        String dateToString = date2.toString();
        if (dateToString.contains(":00:00")) continue;
        if (dateToString.contains(":30:00")) continue;
        System.out.println(tz + ' ' + dateToString);
    }
    

    1900年以前,很少有时区产生这种结果(也许这些是不准确的结果)

        4
  •  0
  •   Dean J    15 年前

    向上面的Jarnbjo投赞成票,Joda Time会帮你解决任何问题吗?

    Java日期/时间/日历库有时有点损坏。