私は奇妙な行動に出くわし、好奇心旺盛で、まだ満足のいく説明がありません.
簡単にするために、気付いた症状を次のコードに減らしました。
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="アメリカ/ロサンゼルス",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="アメリカ/ロサンゼルス",offset=-28800000,dstSavings=3600000,useDaylight =true,transitions=185,lastRule=java.util.SimpleTimeZone[id=アメリカ/ロサンゼルス,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つを比較する最も簡単な方法です. 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の Javadoc には、実際にこれがある程度文書化されていることがわかります。
「省略された年パターン ("y" または "yy") で解析するために、SimpleDateFormat は、ある世紀に関連する省略された年を解釈する必要があります。これは、SimpleDateFormat インスタンスの時刻の 80 年前と 20 年後の日付を調整することによって行われます。創造された。"
そのため、解析対象の日付の年にこだわる代わりに、デフォルトで内部カレンダーを 80 年戻します。その部分自体は文書化されていませんが、それについて知っていると、すべての部分がうまく収まります。