我对Java很新,我试图弄清楚GregorianCalendar的奇怪之处。似乎年份设置不正确(有时候。)
我做了以下测试功能,以说明问题:
<rule ref="rulesets/java/design.xml/UseSingleton"/>
此函数接受Calendar对象,并生成如下所示的输出:
public static void testTime(Calendar c) {
SimpleDateFormat sdf =
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+0"));
System.out.println("---------------------------------");
c.setTimeInMillis(0);
Date d = c.getTime();
System.out.println("Time 0: " + sdf.format(d) +
" (" + d.getTime() + ")");
c.set(Calendar.YEAR, 2000);
d = c.getTime();
System.out.println("Year 2000: " + sdf.format(d) +
" (" + d.getTime() + ")");
System.out.println("---------------------------------");
}
我从主要调用该函数3次;调用它的代码如下:
---------------------------------
Time 0: 1970/01/01 00:00:00 (0)
Year 2000: 2000/01/01 00:00:00 (946684800000)
---------------------------------
最后,这是输出:
Calendar c = GregorianCalendar.getInstance();
testTime(c);
c.setTimeZone(TimeZone.getTimeZone("GMT+0"));
testTime(c);
c.setTimeZone(TimeZone.getTimeZone("America/Phoenix"));
testTime(c);
正如您所看到的,当我使用从getInstance()获得的GregorianCalendar调用函数时,或者将时区设置为 “America / Phoenix”(我当地时区),年份输出为2001 。当我将时区设置为GMT时,年份(正确地说我相信)输出为 2000 。
有人可以向我解释一下我错过了什么吗?我想通过创建一个日历,使用我拥有的一些变量设置一些字段,并生成日期来使用日历。但是,我需要确保我回来的日期确实能够准确反映我的设定;我的单元测试让我有点疯狂,直到我意识到我的日期回来时与我输入的年份不符,所以我做了上面的代码测试。
编辑:要明确,我不关心由于时区造成的小偏移。我可以理解,并解释。由于时区而导致+ -24小时的时差是一回事;一年的时间差(2001年而不是2000年)是另一个时间差。
如果重要,这个Java运行在64位Linux机器上; java -showversion命令返回:
---------------------------------
Time 0: 1970/01/01 00:00:00 (0)
Year 2000: 2001/01/01 00:00:00 (978307200000)
---------------------------------
---------------------------------
Time 0: 1970/01/01 00:00:00 (0)
Year 2000: 2000/01/01 00:00:00 (946684800000)
---------------------------------
---------------------------------
Time 0: 1970/01/01 00:00:00 (0)
Year 2000: 2001/01/01 00:00:00 (978307200000)
---------------------------------
提前感谢您的帮助。我尽可能多地搜索了这里的电路板和互联网,找不到任何与我的问题相近的东西。
答案 0 :(得分:1)
好的,我知道发生了什么。
当我设置年份时,它确实将年份设置为2000.然后它似乎使用它所具有的时区更新其余的内部字段。
这意味着当我将年份设置为2000时,它会设置该字段,并计算时间(包括时区)。前一次是1970年1月1日00:00:00。它将年份更新为2000年,将时间移回7小时(我的偏移量),时间为12月31日17:00 MST。这一年应该真的回到1999年,但它将在2000年离开,因为这是我设定的。因此产生的日期是2000年12月31日17:00。
当我打印日期时,我将SimpleDateFormat的时区设置为GMT。因此,它将时间向前移动7小时,至2001年1月1日00:00:00。
这确实令人困惑,但重复的测试表明它确实是这样做的。奇怪但真实。这里的教训(对我来说)是我应该设置输出对象的时区以匹配日历的时区。然后它会显示与我输入的日期相符的日期。
答案 1 :(得分:0)
当您尝试将新值与新YEAR重新分配给Date对象时,会出现问题。 这段代码:
this.startDatePicker.MinDate = System.DateTime.Now;
this.startDatePicker.Value = System.DateTime.Now;
不起作用。但是这一个:
c.setTimeInMillis(0);
Date d = c.getTime();
System.out.println("Time 0: " + sdf.format(d) +
" (" + d.getTime() + ")");
适用于我的#34;没有时区&#34;情况下。
对于美国/菲尼克斯案,这就是问题所在:
c.setTimeInMillis(0);
System.out.println("Time 0: " + sdf.format(c.getTime()) +
" (" + c.getTime() + ")");
但您可以将其替换为
c.setTimeInMillis(0);
它会起作用。