SimpleDateFormatで短縮年"yy"を指定した時の解析ルール

年が明けてからデイリービルドでコケるテストがあったんで,調べてみたらこんなテストケースだった.

    DateFormat df = new SimpleDateFormat("yy");
    Date date = df.parse("27");
    assertEquals(1927 - 1900, date.getYear());

デバッグしてみたら,今年になってから 27 が 1927年じゃなくて2027年と解釈されてるらしい.


なんじゃそりゃ?と思ってJavadoc見てみたら,ちゃんと制約として書いてあった.

短縮年パターン ("y" または "yy") で解析するときは、SimpleDateFormat は特定の世紀に合わせて短縮年を解釈する必要があります。この解釈は、SimpleDateFormat のインスタンスの生成前の 80 年以内から生成後の 20 年以内に日付を調整することによって行われます。たとえば、"MM/dd/yy" のパターンと 1997 年 1 月 1 日に生成された SimpleDateFormat のインスタンスを使うと、"01/11/12" という文字列は 2012 年 1 月 11 日と解釈され、"05/04/64" という文字列は 1964 年 5 月 4 日と解釈されます。
Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle

"SimpleDateFormat のインスタンスの生成前の 80 年以内から生成後の 20 年以内に日付を調整することによって行われます。"ってイマイチ不明瞭なんで,英語のほうもみてみる.

For parsing with the abbreviated year pattern ("y" or "yy"), SimpleDateFormat must interpret the abbreviated year relative to some century. It does this by adjusting dates to be within 80 years before and 20 years after the time the SimpleDateFormat instance is created. For example, using a pattern of "MM/dd/yy" and a SimpleDateFormat instance created on Jan 1, 1997, the string "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64" would be interpreted as May 4, 1964.
SimpleDateFormat (Java 2 Platform SE 5.0)

ってさ,日付に対して"after"や"before"が,厳密にどうゆう意味を持つか分かるだけの英語力があるというのか?>自分


論よりコードってことで,結論はこうだ.

基準年をYとすると「Y-80 < x <= Y+20」

なんで,2006年までは上限が2026年までだったんで,27は1927と解釈されたんだけど,2007年になって上限が2027年まで伸びたので,27は2027年と解釈されるようになった.
というワケ.


このコケたテストコード,初めに組んだのは4〜5年前だと思うが,長い年月を経てこんな仕様に気づかせてくれるとは思いもよらなかった.
2000年問題も,こんな気分だったんだろうか.