Java Calendar.roll DST begin/end 值不正确
Java Calendar.roll over DST begin/end has incorrect values
当您尝试在 DST 开始或结束的那一天滚动时会出现此问题。例如我们可以使用 "America/New_York" 时区设置 01/11/2015 到日历(EDT 更改为 EST 的那一天)并尝试滚动:
TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
Calendar cal = Calendar.getInstance(timeZone);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
formatter.setTimeZone(timeZone);
cal.set(Calendar.YEAR, 2015);
cal.set(Calendar.MONTH, 10);
cal.set(Calendar.DAY_OF_MONTH, 1);
for (int i = 0; i < 24; i++)
{
cal.roll(Calendar.HOUR_OF_DAY, 1);
System.out.println("Formatted date: " + formatter.format(cal.getTime()));
}
这是结果:
...
格式化日期:2015.11.01 22:08:32 EST
格式化日期:2015.11.01 23:08:32 EST
格式化日期:2015.11.01 01:08:32 EDT
格式化日期:2015.11.01 01:08:32 EST
格式化日期:2015.11.01 02:08:32 EST
...
看看 roll
javadoc。
This default implementation on Calendar just repeatedly calls the version of roll() that rolls by one unit. This may not always do the right thing.
如果您改用 Calendar.add
并在 10 月 31 日开始,您将看到正确的输出 --
Formatted date: 2015.10.31 21:33:31 EDT
Formatted date: 2015.10.31 22:33:31 EDT
Formatted date: 2015.10.31 23:33:31 EDT
Formatted date: 2015.11.01 00:33:31 EDT
Formatted date: 2015.11.01 01:33:31 EDT
Formatted date: 2015.11.01 01:33:31 EST
Formatted date: 2015.11.01 02:33:31 EST
Formatted date: 2015.11.01 03:33:31 EST
由于您必须使用 roll
,因此添加一些自定义逻辑来确定 EST 翻转点并相应地进行调整。它有点老套,但这里有一个简单的例子:
TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
Calendar cal = Calendar.getInstance(timeZone);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
formatter.setTimeZone(timeZone);
cal.set(Calendar.YEAR, 2015);
cal.set(Calendar.MONTH, 10);
cal.set(Calendar.DAY_OF_MONTH, 1);
boolean isPreviousHour23 = (cal.get(Calendar.HOUR_OF_DAY) == 23);
for (int i = 0; i < 25; i++) {
cal.roll(Calendar.HOUR_OF_DAY, 1);
if(isPreviousHour23){
cal.roll(Calendar.HOUR_OF_DAY, -1);
}
isPreviousHour23 = (cal.get(Calendar.HOUR_OF_DAY) == 23);
System.out.println("Formatted date: " + formatter.format(cal.getTime()));
}
给你这个输出:
Formatted date: 2015.11.01 22:24:13 EST
Formatted date: 2015.11.01 23:24:13 EST
Formatted date: 2015.11.01 00:24:13 EDT
Formatted date: 2015.11.01 01:24:13 EDT
Formatted date: 2015.11.01 01:24:13 EST
Formatted date: 2015.11.01 02:24:13 EST
Formatted date: 2015.11.01 03:24:13 EST
Formatted date: 2015.11.01 04:24:13 EST
当您尝试在 DST 开始或结束的那一天滚动时会出现此问题。例如我们可以使用 "America/New_York" 时区设置 01/11/2015 到日历(EDT 更改为 EST 的那一天)并尝试滚动:
TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
Calendar cal = Calendar.getInstance(timeZone);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
formatter.setTimeZone(timeZone);
cal.set(Calendar.YEAR, 2015);
cal.set(Calendar.MONTH, 10);
cal.set(Calendar.DAY_OF_MONTH, 1);
for (int i = 0; i < 24; i++)
{
cal.roll(Calendar.HOUR_OF_DAY, 1);
System.out.println("Formatted date: " + formatter.format(cal.getTime()));
}
这是结果:
...
格式化日期:2015.11.01 22:08:32 EST
格式化日期:2015.11.01 23:08:32 EST
格式化日期:2015.11.01 01:08:32 EDT
格式化日期:2015.11.01 01:08:32 EST
格式化日期:2015.11.01 02:08:32 EST
...
看看 roll
javadoc。
This default implementation on Calendar just repeatedly calls the version of roll() that rolls by one unit. This may not always do the right thing.
如果您改用 Calendar.add
并在 10 月 31 日开始,您将看到正确的输出 --
Formatted date: 2015.10.31 21:33:31 EDT
Formatted date: 2015.10.31 22:33:31 EDT
Formatted date: 2015.10.31 23:33:31 EDT
Formatted date: 2015.11.01 00:33:31 EDT
Formatted date: 2015.11.01 01:33:31 EDT
Formatted date: 2015.11.01 01:33:31 EST
Formatted date: 2015.11.01 02:33:31 EST
Formatted date: 2015.11.01 03:33:31 EST
由于您必须使用 roll
,因此添加一些自定义逻辑来确定 EST 翻转点并相应地进行调整。它有点老套,但这里有一个简单的例子:
TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
Calendar cal = Calendar.getInstance(timeZone);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
formatter.setTimeZone(timeZone);
cal.set(Calendar.YEAR, 2015);
cal.set(Calendar.MONTH, 10);
cal.set(Calendar.DAY_OF_MONTH, 1);
boolean isPreviousHour23 = (cal.get(Calendar.HOUR_OF_DAY) == 23);
for (int i = 0; i < 25; i++) {
cal.roll(Calendar.HOUR_OF_DAY, 1);
if(isPreviousHour23){
cal.roll(Calendar.HOUR_OF_DAY, -1);
}
isPreviousHour23 = (cal.get(Calendar.HOUR_OF_DAY) == 23);
System.out.println("Formatted date: " + formatter.format(cal.getTime()));
}
给你这个输出:
Formatted date: 2015.11.01 22:24:13 EST
Formatted date: 2015.11.01 23:24:13 EST
Formatted date: 2015.11.01 00:24:13 EDT
Formatted date: 2015.11.01 01:24:13 EDT
Formatted date: 2015.11.01 01:24:13 EST
Formatted date: 2015.11.01 02:24:13 EST
Formatted date: 2015.11.01 03:24:13 EST
Formatted date: 2015.11.01 04:24:13 EST