Excelの1900/2/29をPOIで取得してみる
1900年は閏年ではない。
しかし、Excelのバグで1900/2/29という日付を設定できてしまう。
これをJavaからPOIで取得するとどうなるか?を試してみた。
ほんとうはExcelファイルを作って、POIで読み込んで…、とするべきなんだろうけど、面倒なのでPOIのDataUtil.getJavaDateに直接シリアル値を渡してみる。
Excelでは、1900/2/29のシリアル値は60。
その前後の値をDateで表示してみる。
DateFormat format = new SimpleDateFormat("yyyy/MM/dd"); System.out.println(format.format(DateUtil.getJavaDate(59))); System.out.println(format.format(DateUtil.getJavaDate(60))); System.out.println(format.format(DateUtil.getJavaDate(61)));
結果は、
1900/02/28 1900/03/01 1900/03/01
で、1900/2/29は1900/3/1になるようだ。
POIのソースを見ると、org.apache.poi.ss.usermodel.DateUtil#setCalendarに以下のようなコードがあった。
int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't … if (wholeDays < 61) { // Date is prior to 3/1/1900, so adjust because Excel thinks 2/29/1900 exists // If Excel date == 2/29/1900, will become 3/1/1900 in Java representation dayAdjust = 0; }
なるほど。60と61の間で分岐している。
気になってOpenOfficeでも試してみたところ、「1900/2/29」は日付として認識されなかった。Excelとの比較は下の通り。
シリアル値 | OpenOffice | Excel |
---|---|---|
59 | 1900/2/27 | 1900/2/28 |
60 | 1900/2/28 | 1900/2/29 |
61 | 1900/3/1 | 1900/3/1 |
互換製品を作るとき、バグもそのまま移植するかどうかは、悩むところだろうなあ。
POI : 3.11
OpenOffice: 4.1.1