Java 一个月休假(不是因为它是基于0的)

Java 一个月休假(不是因为它是基于0的),java,date,Java,Date,当我将月份设置为代表1970年1月1日的日期,然后立即将月份取回时,它的值为1 import java.util.Date; @Test public void monthShouldBeExpectedValue() { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date(0)); int expectedMonth = Calendar.JUNE; calendar.s

当我将月份设置为代表1970年1月1日的日期,然后立即将月份取回时,它的值为1

import java.util.Date;

@Test
public void monthShouldBeExpectedValue() {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(new Date(0));

    int expectedMonth = Calendar.JUNE;
    calendar.set(Calendar.MONTH, expectedMonth);
    int actualMonth = calendar.get(Calendar.MONTH);

    assertThat(actualMonth, equalTo(expectedMonth)); // test fails: expected 5 got 6
}
如果我换这条线

calendar.setTime(new Date(0));

然后测试通过了。有人知道为什么吗

编辑

日期的印刷版本如下:

new Date(0):         Wed Dec 31 19:00:00 EST 1969
date from calendar:  Tue Jul 01 19:00:00 EDT 1969
我正在运行一个旧的JDK:1.6.0_30-b12(64位)


我现在是东部标准时间。

首先,打印日历以获得准确的日期

然后是常见的问题:

你的时区是什么

你有暑期储蓄吗

你的时区自1970年以来有变化吗


问题通常是,与每月第一天的午夜相比,你少了一个小时,即上个月最后一天的深夜。

我的猜测是,由于你当前的时区,时间被解释为1969年12月31日+几个小时。因此,将月份设置为6月将导致1969年6月31日(该日期不存在;6月有30天)。因此,它将滚动到7月份。

这是正确的

乔达时间 为了好玩,我在2.3中尝试了类似的代码

同样的行为,这是有道理的。如果您要求从零纪元开始以毫秒为单位构造一个,您将得到1970年1月1日的开始日期。但这是UTC中的日期时间(无时区偏移)

如果使用用户的默认时区对DateTime对象调用toString(),当然会看到除(1970年1月1日的开始日期)之外的其他值。除非用户是,否则他们全年都在使用

示例代码
DateTime epoch=newdatetime(0);
System.out.println(“历元:+0”);
System.out.println(“UTC中的历元:+zero.toDateTime(DateTimeZone.UTC));
在美国西海岸默认时区运行时

时代:1969-12-31T16:00:00.000-08:00 UTC中的历元:1970-01-01T00:00:00.000Z 故事的寓意 始终指定时区;永远不要假设

处理没有明确已知时区的日期时间值就像处理没有明确已知字符编码的文本文件一样。不聪明

六月 在一行代码中使用Joda Time来完成问题的答案

System.out.println(“纪元后的六月:+new DateTime(0).toDateTime(DateTimeZone.UTC).monthOfYear().setCopy(DateTimeConstants.June));
当运行时

纪元后的六月:1970-06-01T00:00:00.000Z

这种代码足够聪明,可以处理月底的问题。如果原来是1月31日,结果将是6月30日。

无法复制。。。(OpenJDK 1.7.0_25)无法在我当前的语言环境中复制jdk1.6.0_45,我得到了大纪元时间
31/12/1969 21hs
calendar.set(calendar.MONTH,5)
然后显示
calendar.getTime
我得到了
July
MONTH,这就是为什么你得到6,但我不知道为什么你在设置月份时,我也在东部时间,我确实看到了这种行为。但是如果我将行更改为
calendar.setTime(新日期(86400000))(1天后)然后一切正常,日历上的日期是1970年6月1日,而不是1969年7月1日。我正在运行JDK1.7.0_25。我在EST中,也可以复制结果,就像dcsohl一样。这就是情况(很好的发现)。0毫秒将是从1970年1月1日开始的UTC时间,我们的偏移量为-5小时。太棒了!如果我将
expectedMonth
更改为
Calendar.JULY
,该日历有31天,则测试通过。干得好!!使用任何负GMT偏移量
Calendar.getInstance(TimeZone.getTimeZone(“GMT-1:00”))进行测试表明这是正确的。6月没有31天的好消息:Dan其他可能的解决方法是使用
新日期(12*60*60)
而不是
新日期(0)
(即1970-01-01T12:00:00Z而不是1970-01-01T00:00:00Z)。时间偏移范围从-12到+14,因此无论您处于哪个区域,它都不能在历元之前生成日期(但它可以在月的第二天生成日期)。
new Date(0):         Wed Dec 31 19:00:00 EST 1969
date from calendar:  Tue Jul 01 19:00:00 EDT 1969