我遇到了一种奇怪的行为,这让我很好奇,但还没有令人满意的解释。
为简单起见,我已将注意到的症状简化为以下代码:
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
public class CalendarTest {
public static void main(String[] args) {
System.out.println(new SimpleDateFormat().getCalendar());
System.out.println(new GregorianCalendar());
}
}
当我运行此代码时,我得到与以下输出非常相似的内容:
java.util.GregorianCalendar[time=-1274641455755,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000, useDaylight=true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8 ,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1 ,YEAR=1929,MONTH=7,WEEK_OF_YEAR=32,WEEK_OF_MONTH=2,DAY_OF_MONTH=10,DAY_OF_YEAR=222,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=8,HOUR_OF_DAY=20,MINUTE=55,SECOND =44,MILLISECOND=245,ZONE_OFFSET=-28800000,DST_OFFSET=0] java.util.GregorianCalendar[time=1249962944248,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Los_Angeles",offset=-28800000,dstSavings=3600000,useDaylight =true,transitions=185,lastRule=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8, startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1, YEAR=2009,MONTH=7,WEEK_OF_YEAR=33,WEEK_OF_MONTH=3,DAY_OF_MONTH=10,DAY_OF_YEAR=222,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=8,HOUR_OF_DAY=20,MINUTE=55,SECOND= 44,MILLISECOND=248,ZONE_OFFSET=-28800000,DST_OFFSET=3600000]
"yyyy-MM-dd"
(如果我提供像SimpleDateFormat这样的有效格式字符串,也会发生同样的事情。)
原谅可怕的非环绕线,但这是比较两者的最简单方法。如果滚动到大约 2/3 处,您会看到日历的 YEAR 值分别为 1929 和 2009。(还有一些其他差异,例如一年中的星期、星期和 DST 偏移量。)两者显然都是 GregorianCalendar 的实例,但它们不同的原因令人费解。
据我所知,格式化程序在格式化传递给它的 Date 对象时会产生准确的结果。显然,正确的功能比正确的参考年份更重要,但这种差异仍然令人不安。我不认为我必须在全新的日期格式化程序上设置日历才能获得当前年份......
我已经在使用 Java 5(OS X 10.4,PowerPC)和 Java 6(OS X 10.6,Intel)的 Mac 上进行了测试,结果相同。由于这是一个 Java 库 API,我假设它在所有平台上的行为都相同。对这里正在发生的事情有任何见解吗?
(注意:这个 SO 问题有些相关,但不一样。)
编辑:
下面的答案都有助于解释这种行为。事实证明,SimpleDateFormat的 Javadocs实际上在某种程度上记录了这一点:
“对于使用缩写年份模式(“y”或“yy”)进行解析,SimpleDateFormat 必须解释相对于某个世纪的缩写年份。它通过将日期调整为 SimpleDateFormat 实例时间之前的 80 年和之后的 20 年来实现这一点被建造。”
因此,他们并没有对解析日期的年份感到好奇,而是默认将内部日历设置回 80 年。该部分本身没有记录,但是当您了解它时,所有部分都可以组合在一起。