Я столкнулся со странным поведением, которое оставило меня любопытным и без удовлетворительного объяснения.
Для простоты я сократил отмеченные симптомы до следующего кода:
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 пути, вы увидите, что календари имеют значения ГОД 1929 и 2009 соответственно. (Есть несколько других отличий, таких как неделя года, день недели и смещение летнего времени.) Очевидно, что оба они являются экземплярами GregorianCalendar, но причина, по которой они различаются, вызывает недоумение.
Из того, что я могу сказать, средство форматирования выдает точные значения при форматировании объектов Date, передаваемых в него. Очевидно, что правильная функциональность важнее правильного отчетного года, но расхождение, тем не менее, приводит в замешательство. Я бы не подумал, что мне нужно установить календарь на совершенно новый форматер даты, чтобы получить текущий год ...
Я тестировал это на Mac с Java 5 (OS X 10.4, PowerPC) и Java 6 (OS X 10.6, Intel) с теми же результатами. Поскольку это API-интерфейс библиотеки Java, я предполагаю, что он ведет себя одинаково на всех платформах. Любое понимание того, что здесь происходит?
(Примечание: Этот вопрос SO несколько связан, но не совпадает.)
Edit:
Ответы ниже всех помогли объяснить это поведение. Оказывается, что Javadocs для SimpleDateFormat фактически документируют это в некоторой степени:
"Для синтаксического анализа с сокращенным шаблоном года (" y "или" yy ") SimpleDateFormat должен интерпретировать сокращенный год относительно некоторого столетия. Он делает это, корректируя даты так, чтобы они были в пределах 80 лет до и 20 лет после экземпляр SimpleDateFormat создан. "
Таким образом, вместо того, чтобы придумывать год разбора даты, они просто устанавливают внутренний календарь на 80 лет по умолчанию. Эта часть сама по себе не задокументирована, но когда вы узнаете об этом, все части соединяются вместе.