tpo*_*eba 12 java gregorian-calendar
我观察到java.util.GregorianCalendar的一个奇怪的行为,我想知道它为什么会这样.
我希望得到UTC的时间,这是同一时刻26.10.2014 01:00 CET,然后在同一天获得UTC午夜.所以首先我设置实际的CET日期,而不是将时区更改为UTC,最后将HOUR_OF_DAY设置为0.
例:
请参阅下面的junit代码:
@Test
public void testWeird() {
GregorianCalendar date = (GregorianCalendar) GregorianCalendar.getInstance(TimeZone.getTimeZone("CET"));
date.set(2014, 9, 26, 1, 0, 0); //26.10.2014
System.out.println(date.getTime().toGMTString() + " " + date.getTimeInMillis()); // 25 Oct 2014 23:00:00 GMT 1414278000764 (OK)
date.setTimeZone(TimeZone.getTimeZone("UTC"));
//date.get(Calendar.YEAR); // uncomment this line to get different results
System.out.println(date.getTime().toGMTString() + " " + date.getTimeInMillis()); // 25 Oct 2014 23:00:00 GMT 1414278000764 (OK)
date.set(Calendar.HOUR_OF_DAY, 0);
System.out.println(date.getTime().toGMTString() + " " + date.getTimeInMillis()); // 26 Oct 2014 00:00:00 GMT 1414281600764 (NOT OK! why not 25 Oct 2014 00:00:00 GMT 1414195200218 ?)
}
Run Code Online (Sandbox Code Playgroud)
我预计设置小时= 0 25.10.2014 23:00 GMT会给我25.10.2014 00:00 GMT,但它改为26.10.2014 00:00 GMT.
但是,如果我取消注释行date.get(Calendar.YEAR);,则日期似乎正确计算.
jdk.1.7.0_10和jrockit-jdk1.6.0_37也是如此.
由于GregorianCalender扩展了Calendar类,它继承了它的所有功能.来自Java Doc
set(f, value) changes calendar field f to value. In addition, it sets an internal
member variable to indicate that calendar field f has been changed. Although
calendar field f is changed immediately, the calendar's time value in
milliseconds is not recomputed until the next call to get(), getTime(),
getTimeInMillis(),add(), or roll() is made. Thus, multiple calls to set() do not
trigger multiple, unnecessary computations. As a result of changing a calendar
field using set(), other calendar fields may also change, depending on the calendar
field, the calendar field value, and the calendar system. In addition, get(f) will
not necessarily return value set by the call to the set method after the calendar
fields have been recomputed.
Run Code Online (Sandbox Code Playgroud)
Java Doc示例:
Consider a GregorianCalendar originally set to August 31, 1999. Calling
set(Calendar.MONTH, Calendar.SEPTEMBER) sets the date to September 31, 1999. This
is a temporary internal representation that resolves to October 1, 1999 if
getTime()is then called. However, a call to set(Calendar.DAY_OF_MONTH, 30) before
the call to getTime() sets the date to September 30, 1999, since no recomputation
occurs after set() itself.
Run Code Online (Sandbox Code Playgroud)
此外日历类具有以下副作用: -
In lenient mode, all of the Calendar fields are normalized.
Run Code Online (Sandbox Code Playgroud)
这意味着当你调用setTimeZone(&时set(Calendar.HOUR_OF_DAY, 0),它设置内部成员变量以指示日历字段已设置.但是日历的时间当时没有重新计算.日历的时间仅一个电话后,重新计算到 get(),getTime(),getTimeInMillis(),add(),或roll()制成.
这是Calendar类 JDK-4827490中的错误:(cal)Doc:Calendar.setTimeZone行为未记录
现在,您的示例已修改为使其工作如下: -
public class DateTimeTest {
@SuppressWarnings("deprecation")
public static void main(String[] args) {
GregorianCalendar date = (GregorianCalendar) GregorianCalendar.getInstance(TimeZone
.getTimeZone("CET"));
// 26.10.2014 01:00:00
date.set(2014, 9, 26, 1, 0, 0);
// 25 Oct 2014 23:00:00 GMT 1414278000764
System.out.println("CET to UTC : " + date.getTime().toGMTString() + " "
+ date.getTimeInMillis());
date.setTimeZone(TimeZone.getTimeZone("UTC"));
// date.roll(Calendar.HOUR_OF_DAY, true); //uncomment this line & comment below line & check the different behavior of Calender.
date.get(Calendar.HOUR_OF_DAY);
// 25 Oct 2014 23:00:00 GMT 1414278000764
System.out.println("UTC : " + date.getTime().toGMTString() + " "
+ date.getTimeInMillis());
date.set(Calendar.HOUR_OF_DAY, 0);
// 25 Oct 2014 00:00:00 GMT 1414195200218
System.out.println("UTC Midnight : " + date.getTime().toGMTString() + " "
+ date.getTimeInMillis());
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
CET to UTC : 25 Oct 2014 23:00:00 GMT 1414278000008
UTC : 25 Oct 2014 23:00:00 GMT 1414278000008
UTC Midnight : 25 Oct 2014 00:00:00 GMT 1414195200008
Run Code Online (Sandbox Code Playgroud)
我希望您现在可以清楚地了解Calendar类的不可预测的行为.
| 归档时间: |
|
| 查看次数: |
4588 次 |
| 最近记录: |