Java 从GregoriaCalendar中减去一天时,小时数已损坏

Java 从GregoriaCalendar中减去一天时,小时数已损坏,java,datetime,Java,Datetime,我使用以下代码: 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 d

我使用以下代码:

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

编辑:


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

您使用的是最新的java版本吗?检查一下,因为在我的java安装(1.6.0_16)上它工作正常,所以输出是:

Sat Apr 04 00:00:00 GMT 1942
Fri Apr 03 00:00:00 GMT 1942
Sun通常会在java更新上更新时区数据库,所以请检查您使用的是最新版本

或者,其他事情:


也许这和夏令时有关?美国政府在二战期间引入了夏令时,这可能是你所在时区的原因,而不是我所在时区的原因

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

图书馆似乎在猜测“夏季时间” 也许很难为你正在做的事情定义“正确答案”东欧夏季时间在1942年不存在。即使是在写了图书馆代码的美国,那一年也没有DST,因为1942年的《战时法案》使那一整年的时间发生了变化

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


我的猜测是,如果EEST存在于1942年,该程序正在错误地应用DST移位,或者只是对可能发生的情况进行最佳猜测。

我想您使用的是芬兰时区。在芬兰,夏时制是在1942年引入的,它将时钟从4月2日23:59:59调整到4月3日1:00:00。4月3日0:00:00到0:59:59的时间跨度不存在,因此Java日历会产生最佳结果

我将为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日,将整个国家置于日期线的一侧。在这一变化之前,国家的时区跨度只有几个小时,但由于被日期线分割,国家实际上有两个不同的日期。

1。他不在美国时区。2.DST在二战前几十年引入美国。3.1942年,甚至在美国也没有DST,确切地说,整个一年都是时移的。代码对我来说也很好…所以检查一下版本,时区etc@DigitalRoss-刚刚用Joda作为DateTime c2=新的DateTime(DateTimeZone.forID(“欧洲/赫尔辛基”)。withYear(1942)测试了这一点。WithMonthHofYear(4)。withDayOfMonth(4)。WithHouOfDay(0)。分钟(0),秒(0),毫秒(0);然后,第1天,同样的问题+1因为你的假设事实上他使用的EEST用于芬兰,所以你的答案似乎是正确的解决方案。我使用欧洲/赫尔辛基时区,我更新了帖子。我没有检查这个,但答案对我来说是合理的。谢谢坏的是我需要迭代日期,找出日期之间的距离等等。。。我对时间一点也不感兴趣!我决定手写。我不想使用Joda,因为我正在编写applet,不想让用户每次都下载Joda。此外,我没有使用Joda,但从fvu的评论来看,它似乎没有解决问题。这可能是可行的,但我已经实现了精确的解决方案,根本不使用时间,只使用日期。事实上,我不想因为其他一些意想不到的惊喜而再次陷入困境,例如闰秒或其他。实现函数getDateIndex(年、月、日){大约返回(年1)*4-(年1)*100+(年1)*400+从年开始的天数(月、日)}