Apache POI でExcel 日付読込み

久々に JavaExcel を読込む apache POI を使う。

try(InputStream is = new FileInputStream("sample.xlsx");
       XSSFWorkbook book = new XSSFWorkbook(is)){
     XSSFSheet sheet = book.getSheetAt(0);
     XSSFRow row = sheet.getRow(2);
     XSSFCell cell = row.getCell(1);

org.apache.poi.ss.usermodel.CellType は、NUMERIC であり、getNumericCellValue() で値を参照する必要がある。
参照する型は、double である。
だから、

cell.getNumericCellValue()

は、double であり、しかも、Excel の EPOCH 基準日は特殊である。
これを java.util.Date に変換するものが、
apache POI には用意されている。

org.apache.poi.ss.usermodel.DateUtil

getJavaDate(double date)

が、 java.util.Date を返す。
でも、 java.util.Date なんかもう使わないので、 java.time.LocalDate にする。

Date date = org.apache.poi.ss.usermodel.DateUtil.getJavaDate(cell.getNumericCellValue());
LocalDate loaldate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

Excel の EPOCH 基準日が特殊というのは、
(UTC)Unix Epoch Time 1970 年 1月1日 0時0分0秒からを基準ではなく、
1900年 1月1日 0時0分0秒 を Excel が基準にしていることだ。
だから、org.apache.poi.ss.usermodel.DateUtil
変換メソッドが提供されている。

stackoverflow に以下の記事があるが、、
https://stackoverflow.com/questions/19028192/converting-number-representation-of-date-in-excel-to-date-in-java
確かに
1900年1月1日より後ろの日付では、

 LocalDate.of(1899, 12, 30).plusDays((long)cell.getNumericCellValue())

という計算もできるであろうが、1900年 1月1日である double 値 1.0 に対しては使えない。

1899-12-31

になってしまう。