我正在尝试使用 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 日期 - 即使我已经从中生成了它。
我错过了什么……?
最佳答案
Excel
1900 年日期系统中的日期值从值 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)
date
时失败是 Java
日期Sun Dec 31 00:00:00 GMT 1899
或 Sun Dec 31 12:00:00 GMT 1899
.但是
DateUtil.getJavaDate(excelDate)
当 excelDate
时返回 1899 年 12 月 31 日是 double
来自 0.0
的值至0.999...
.那是因为没有Java
日期 1900 年 1 月 0 日可能。但是有Excel
日期值可能来自 0.0
至0.999...
.换句话说,
Excel
来自 0.0
的日期值至0.999...
是实际时间值之前 Excel
中第一个可能的一整天,即 1900 年 1 月 1 日的日期。它们实际上不是在一天中,而是在第 0 天。从
0.0
开始的日期值至0.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 日开始转换。然后减去 1
来自 DateUtil.getExcelDate
的结果.
关于java - POI - 在 Excel 和 Java 日期之间转换的问题,反之亦然,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60568161/