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

从公历日历中减去一天时损坏的小时数

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

    我使用以下代码:

    Calendar calendar = new GregorianCalendar(0,0,0);
    calendar.set(Calendar.YEAR, 1942);
    calendar.set(Calendar.MONTH, 3);
    calendar.set(Calendar.DAY_OF_MONTH, 4);
    
    Date date1 = calendar.getTime();
    
    calendar.add(Calendar.DAY_OF_MONTH, -1);
    
    Date date2 = calendar.getTime();
    
    System.out.println(date1 + "\n" + date2);
    

    此代码输出如下:

    Sat Apr 04 00:00:00 EEST 1942
    Fri Apr 03 01:00:00 EEST 1942
    

    实际上,我减去1天,时间应该保留下来。 但是为什么第二行输出在时间上包含1小时,而它应该是0?

    编辑:

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

    5 回复  |  直到 15 年前
        1
  •  18
  •   jarnbjo    15 年前

    我想你用的是芬兰时区。在芬兰,夏令时是在1942年通过将时钟从4月2日23:59:59调整到4月3日1:00:00引入的。时间跨度为4月3日,0:0:00到0:59:59不存在,因此Java日历做出了最大努力的结果。

        2
  •  1
  •   theomega    15 年前

    你使用的是最新的Java版本吗?检查一下,因为在我的Java安装(1.60EY16)上它工作得很好,输出是:

    Sat Apr 04 00:00:00 GMT 1942
    Fri Apr 03 00:00:00 GMT 1942
    

    Sun通常更新时区数据库上的JAVA更新,所以检查你使用的是最新版本!

    或者,其他事情:

    也许这与日光节约有关?美国政府在第二次世界大战期间引入了日光节约,这可能是你所在时区的原因,但不是我的原因?

        3
  •  1
  •   DigitalRoss    15 年前

    看起来图书馆在“夏季”进行猜测

    可能很难定义” 正确的答案 “为了你所做的。 东欧夏季 不存在于1942年。即使是在图书馆代码可能已经被写的美国,那一年也没有DST,因为1942年的战争时期法案使得这一年的时间被转移了。

    对于Java日期和时间的问题,通常的答案是使用 Joda Time. 我不确定这会有什么帮助,但可能。

    我的猜测是,如果EEST在1942年存在的话,程序错误地应用了DST移位,或者只是对它可能是什么进行了最好的猜测。

        4
  •  0
  •   serg10    15 年前

    得到的结果很可能取决于运行代码的时区。在您的本地时区,1天的时间间隔可能会跨越夏令时的更改,或者您所在国家/地区的其他一次性时钟调整。

        5
  •  0
  •   jarnbjo    15 年前

    我将为serdev的评论写另一个答案,因为单独在评论中包含很多信息有点困难。

    你说你必须迭代日期并找到距离,如果你做了一些假设,这些假设必须对你的地区或时区有效,这并不太困难。如果忽略时间并使用代码从“1942年4月4日星期六”中减去一天,则会得到预期的“1942年4月3日星期五”。如果您需要查找到日期之间的天数,我会自己计算:

    // set two Calendars to April 1st, 1942 and April 5th, 1942 (both 0:00)
    Calendar cal1 = new GregorianCalendar(1942, 3, 1);
    Calendar cal2 = new GregorianCalendar(1942, 3, 5);
    
    // divide the difference in ms by the number of ms in 24 hours and round the result
    long diff = Math.round((cal2.getTimeInMillis() - cal1.getTimeInMillis()) / (24.*60*60*1000));
    

    仅仅用芬兰时区划分就可以得到3.958天的差异,但四舍五入则得到了正确的4天结果。

    但是,要使其生效,您必须假定日期是连续的,并且您的时区在开始日期和结束日期之间的变化不超过11小时。这并不总是正确的,因为在国际日期变更线附近有一些国家会“转换方”。最近的一个案例是基里巴斯的部分地区跳过了1994年12月31日,将整个国家置于日期线的一边。在变化之前,国家的时区只跨越几个小时,但由于它被日期线分割,国家实际上有两个不同的日期。