【发布时间】:2010-11-18 12:14:17
【问题描述】:
我遇到了一种奇怪的行为,这让我很好奇,但还没有令人满意的解释。
为简单起见,我将注意到的症状简化为以下代码:
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]
(如果我向 SimpleDateFormat 提供像 "yyyy-MM-dd" 这样的有效格式字符串,也会发生同样的事情。)
请原谅可怕的非环绕行,但这是比较两者的最简单方法。如果滚动到大约 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,我假设它在所有平台上的行为都相同。对这里正在发生的事情有任何见解吗?
(注意:This SO question 有点相关,但不一样。)
编辑:
以下所有答案都有助于解释这种行为。事实证明,SimpleDateFormat 的 Javadocs 实际上在某种程度上记录了这一点:
“对于使用缩写年份模式(“y”或“yy”)进行解析,SimpleDateFormat 必须解释相对于某个世纪的缩写年份。它通过将日期调整为时间之前的 80 年和之后的 20 年来实现这一点SimpleDateFormat 实例已创建。”
因此,他们只是默认将内部日历设置回 80 年,而不是对被解析日期的年份花哨。该部分本身没有记录,但是当您了解它时,所有部分都可以组合在一起。
【问题讨论】:
标签: java date calendar simpledateformat