簡體   English   中英

POI - 在 Excel 和 Java 日期之間轉換的問題,反之亦然

[英]POI - Problems converting between Excel & Java date & vice-versa

我正在嘗試使用 Apache POI (4.0.1) 在 Excel 工作簿的單元格中節省時間。

我將時間轉換為java.util.Date ,然后嘗試使用org.apache.poi.ss.usermodel.DateUtil.getExcelDate方法將其保存在單元格中。

我發現,由於時間與紀元(1899 年)在同一年,因此getExcelDate中有一個硬編碼檢查,禁止將日期轉換為 1900 年之前的年份,從而阻止我做我所追求的事情。

示例應用:

import java.util.Date;
import java.util.stream.DoubleStream;
import org.apache.poi.ss.usermodel.DateUtil;

public class POIQuery {
    public static void main(final String[] args) {
    final String format = "%-20s%-35s%-20s%n"; //$NON-NLS-1$

    System.out.format(format, "Input Excel Date", "Java Date", "Converted Excel Date");

    DoubleStream.of(0, 0.5d, 1.5d).forEach(excelDate -> {
        final Date date = DateUtil.getJavaDate(excelDate);
        System.out.format(format, excelDate, date, DateUtil.getExcelDate(date));
    });
    }
}

輸出(請注意,根據文檔 - “-1”的“轉換后的 Excel 日期”表示錯誤)。

Input Excel Date    Java Date                          Converted Excel Date
0.0                 Sun Dec 31 00:00:00 GMT 1899       -1.0                
0.5                 Sun Dec 31 12:00:00 GMT 1899       -1.0                
1.5                 Mon Jan 01 12:00:00 GMT 1900       1.5

在這里您可以看到我要求表示 Excel 日期“0.5”的 Java 日期。 然后我使用提供的 Java 日期,但 POI 說沒有與該日期相對應的 Excel 日期 - 即使我已經從中生成了它。

我是不是錯過了什么……?

1900 年日期系統中的Excel日期值從值 0 = 1900 年 1 月的第 0 天開始。在此之前沒有Excel日期值。

如果您在Excel有以下單元格:

     A                  B
1  Value      Excel date
2      0      01/00/1900 00:00:00
3    0.5      01/00/1900 12:00:00
4      1      01/01/1900 00:00:00
5    1.5      01/01/1900 12:00:00

其中B列中的值與A列中的值相同,但使用數字格式MM/DD/YYYY hh:mm:ss格式化為日期,您會看到這一點。

所以沒有Excel日期 1899 年 12 月 31 日。這就是為什么DateUtil.getExcelDate(date)dateJava日期Sun Dec 31 00:00:00 GMT 1899Sun Dec 31 12:00:00 GMT 1899時失敗的原因。

但是DateUtil.getJavaDate(excelDate)返回 1899 年 12 月 31 日,當excelDate是從0.00.999...double DateUtil.getJavaDate(excelDate)值時。 那是因為沒有可能的Java日期 1900 年 1 月 0 日。 但是Excel日期值可能從0.00.999...

換句話說, Excel日期值從0.00.999...實際上是Excel第一個可能的全天之前的實際時間值,即日期 1900 年 1 月 1 日。它們實際上不是在一天中,而是在第 0 天。

由於從0.00.999...日期值和轉換后的Java日期為 1899 年 12 月 31 日是特殊情況,因此可以這樣處理它們。

通過擴展您的代碼:

import java.util.Date;
import java.util.Calendar;
import java.util.stream.DoubleStream;
import org.apache.poi.ss.usermodel.DateUtil;

public class POIQuery {
    public static void main(final String[] args) {
    final String format = "%-20s%-35s%-20s%n"; //$NON-NLS-1$

    System.out.format(format, "Input Excel Date", "Java Date", "Converted Excel Date");

    DoubleStream.of(0, 0.5d, 1d, 1.5d, 44000d, 44000.5d).forEach(excelDate -> {
        final Date date = DateUtil.getJavaDate(excelDate);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        double excelDateFromDate = -1d;
        if (cal.get(Calendar.YEAR) == 1899 && cal.get(Calendar.MONTH) == 11 && cal.get(Calendar.DATE) == 31) {
         cal.add(Calendar.DATE, 1);
         excelDateFromDate = DateUtil.getExcelDate(cal.getTime());
         excelDateFromDate -= 1d; 
        } else {
         excelDateFromDate = DateUtil.getExcelDate(date);
        }
        System.out.format(format, excelDate, date, excelDateFromDate);
    });
    }
}

如果轉換后的Java日期是 1899 年 12 月 31 日,並且我們知道這是從Excel轉換的,那么在將其重新轉換為Excel日期值時,在使用DateUtil.getExcelDate之前先添加一天。 所以DateUtil.getExcelDate從 1900 年 1 月 1 日DateUtil.getExcelDate轉換。然后從DateUtil.getExcelDate的結果中減去1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM