Java POI-Excel和;爪哇日期及日期;反之亦然

Java POI-Excel和;爪哇日期及日期;反之亦然,java,excel,apache-poi,Java,Excel,Apache Poi,我正在尝试使用ApachePOI(4.0.1)在Excel工作簿的单元格中节省时间 我将时间转换为java.util.Date,然后尝试使用org.apache.poi.ss.usermodel.DateUtil.getExcelDate方法将其保存在单元格中 我的发现是,由于时间与纪元(1899年)在同一年,因此在getExcelDate中有一个硬编码的签入,该签入禁止将日期转换为1900年之前的年份,从而阻止我做我要做的事情 示例应用程序: import java.util.Date; im

我正在尝试使用ApachePOI(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));
    });
    }
}
输出(注意,根据文档-转换的Excel日期“-1”表示错误)

在这里您可以看到,我要求的是表示Excel日期“0.5”的Java日期。 然后我使用提供的Java日期,但是POI说没有与之对应的Excel日期——尽管我是根据该日期生成的


我是否遗漏了什么…?

Excel
1900年日期系统中的日期值从值0=1900年1月的第0天开始。在此之前没有
Excel
date值

如果在
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/yyyyy hh:MM:ss
格式化为日期,则可以看到

因此,没有日期为1899年12月31日的
Excel
。这就是为什么
DateUtil.getExcelDate(date)
date
Java
date
Sun Dec 31 00:00 GMT 1899
Sun Dec 31 12:00 GMT 1899
时失败的原因

但是
DateUtil.getJavaDate(excelDate)
返回1899年12月31日,此时
excelDate
0.0
0.999之间的
double
值…
。这是因为没有
Java
1900年1月0日的日期。但是有
Excel
日期值可以从
0.0
0.999…

换句话说,从
0.0
0.999…
Excel
日期值实际上是
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日开始转换。然后从
DateUtil.getExcelDate
的结果中减去
1

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);
    });
    }
}