日历集年份问题

2022-09-04 08:34:32

我尝试了以下代码段:

Calendar c1 = Calendar.getInstance();
c1.set(Calendar.YEAR, 0);
c1.set(Calendar.DAY_OF_YEAR, 1);
Date d1 = c1.getTime();

Calendar c2 = Calendar.getInstance();
c2.setTime(d1);
c2.set(Calendar.YEAR, 2001);
c2.set(Calendar.DAY_OF_YEAR, 1);
System.out.println(c2.getTime().toString());

Calendar c3 = Calendar.getInstance();
c3.set(Calendar.YEAR, 2000);
c3.set(Calendar.DAY_OF_YEAR, 1);
Date d2 = c3.getTime();

Calendar c4 = Calendar.getInstance();
c4.setTime(d2);
c4.set(Calendar.YEAR, 2001);
c4.set(Calendar.DAY_OF_YEAR, 1);
System.out.println(c4.getTime().toString());

结果是:

Wed Jan 01 23:47:00 CET 2001
Mon Jan 01 23:47:00 CET 2001

怎么了?我不应该以这种方式使用日历来设置 YEAR 吗?


答案 1

年份是相对于时代而言的。通过将年份设置为小于或等于 0 的值,日历会通过切换时代(从 AD 到 BC 或从 BC 到 AD)来自动更正此问题。这种行为在其他领域更为人所知。例如,如果将月份设置为负数,则年份会相应地递减。

这些更正不是单独进行的,而是一次性完成的,通常是在您打电话读出结果日期时。getTime()

Calendar c1 = Calendar.getInstance(); // August  16th, 2012 AD
c1.set(Calendar.YEAR, 0);             // August  16th,    0 AD
c1.set(Calendar.DAY_OF_YEAR, 1);      // January  1st,    0 AD
Date d1 = c1.getTime();               // January  1st,    1 BC (corrected)

Calendar c2 = Calendar.getInstance();
c2.setTime(d1);
c2.set(Calendar.YEAR, 2001);          // January  1st, 2001 BC
c2.set(Calendar.DAY_OF_YEAR, 1);
System.out.println(c2.getTime());     // prints "Wed Jan 01 05:35:00 CET 2001"
                                      // because 01/01/2001 BC was a Wednesday

因此,您不必将年份设置为 2001 年,而是必须将其设置为 -2000(因为年份 0 根本不存在)。或者你可以明确地设置时代:

c2.set(Calendar.ERA, GregorianCalendar.AD);

解决此“错误”的另一种方法是读出设置完整日期之前的时间:

Calendar c1 = Calendar.getInstance(); // August  16th, 2012 AD
c1.set(Calendar.YEAR, 0);             // August  16th,    0 AD
c1.set(Calendar.DAY_OF_YEAR, 1);      // January  1st,    0 AD
c1.set(Calendar.YEAR, 2001);          // January  1st, 2001 AD
System.out.println(c1.getTime());     // prints the expected date

要输出日期的纪元,您可以在以下模式中使用“G” :SimpleDateFormat

new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy G").format(c2.getTime())
// "Wed Jan 01 05:35:00 CET 2001 BC"

答案 2

在这两种情况下,在打印输出之前,您都将年份设置为 2001 年。在这两种情况下,产出都反映了当年的情况。您是否期望获得不同的输出?