【发布时间】:2011-10-07 19:14:55
【问题描述】:
使用 java.util.Calendar 将一天添加到 Date,并使用 SimpleDateFormat 显示结果,有时似乎会丢失一天(通常在 3 月),有时会跳过一天(在 11 月)。
下面的程序,带有输出,说明了这个问题。请注意,我只是一次添加一天,然后跳过几个月并再添加几天。你会看到 2008-03-09 被打印了两次,但是 2008-11-02 被跳过了。同样的事情发生在其他年份,但发生在不同的日子。我不得不尝试找出导致问题的日期。
如果我没有在 SimpleDateFormat 中将时区设置为 UTC,那么问题就不会发生。我在美国中部时区的一台机器上运行了这个。
这看起来确实像 Calendar 或 SimpleDateFormat 中的错误,但我无法在任何地方找到它的文档。有人对这里发生的事情有解释吗?
程序:
package mab;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class CalendarHiccup2 {
public static void main(String[] args) {
addDays("2008-03-08");
addDays("2009-03-07");
addDays("2010-03-13");
}
public static void addDays(String dateString) {
System.out.println("Got dateString: " + dateString);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Calendar calendar = Calendar.getInstance();
try {
calendar.setTime(sdf.parse(dateString));
Date day1 = calendar.getTime();
System.out.println(" day1 = " + sdf.format(day1));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day2 = calendar.getTime();
System.out.println(" day2 = " + sdf.format(day2));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day3 = calendar.getTime();
System.out.println(" day3 = " + sdf.format(day3));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day4 = calendar.getTime();
System.out.println(" day4 = " + sdf.format(day4));
// Skipping a few days ahead:
calendar.add(java.util.Calendar.DAY_OF_MONTH, 235);
Date day5 = calendar.getTime();
System.out.println(" day5 = " + sdf.format(day5));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day6 = calendar.getTime();
System.out.println(" day6 = " + sdf.format(day6));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day7 = calendar.getTime();
System.out.println(" day7 = " + sdf.format(day7));
calendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
Date day8 = calendar.getTime();
System.out.println(" day8 = " + sdf.format(day8));
} catch (Exception e) {
}
}
}
输出:
Got dateString: 2008-03-08
day1 = 2008-03-08
day2 = 2008-03-09
day3 = 2008-03-09
day4 = 2008-03-10
day5 = 2008-10-31
day6 = 2008-11-01
day7 = 2008-11-03
day8 = 2008-11-04
Got dateString: 2009-03-07
day1 = 2009-03-07
day2 = 2009-03-08
day3 = 2009-03-08
day4 = 2009-03-09
day5 = 2009-10-30
day6 = 2009-10-31
day7 = 2009-11-02
day8 = 2009-11-03
Got dateString: 2010-03-13
day1 = 2010-03-13
day2 = 2010-03-14
day3 = 2010-03-14
day4 = 2010-03-15
day5 = 2010-11-05
day6 = 2010-11-06
day7 = 2010-11-08
day8 = 2010-11-09
【问题讨论】:
-
发生这种情况时的诀窍是检查您的假设:我只是打印了没有 SDF 的日历本身,问题很明显,因为日历的 TZ 发生了变化。
-
谢谢。通过“打印日历”,我想您的意思是调用 toString()。我又做了几个测试。添加一个日历日时,我的时区 (CST) 中的日历将在“提前”日增加 23 小时,在“后退”日增加 25 小时。如果 SimpleDateFormat 也是 CST,它将正确打印出当天,但如果是 UTC,则添加的 23 小时并不能完全让您到达第二天。而在秋季,增加的 25 小时会超过 UTC 一天。如果日历为 UTC,则始终添加 24 小时。关键是 Calendar 和 SimpleDateFormat 应该在时区上达成一致。
-
如果你真的告诉他们使用相同的 TZ,他们只会在时区上达成一致。 (欢迎来到 Java 时间/日期处理的世界。)
标签: java simpledateformat