17

我在 Excel 中有一个日期列,但是当我在我的 Java 应用程序中读取它时,我得到的值是数字。

例子

Excel 日期

1/1/2013

我把它当作

41275.00

如何在我的 Java 应用程序中将数字转换为日期?

4

5 回答 5

22

这是一个最小的工作示例,如何将 Excel 日期转换为 Java 日期:

        Date javaDate= DateUtil.getJavaDate((double) 41275.00);
        System.out.println(new SimpleDateFormat("MM/dd/yyyy").format(javaDate));

返回

01/01/2013

您还需要导入以下包:

java.text.SimpleDateFormat
java.util.Date
于 2015-09-16T16:56:25.890 回答
16

Apache POI 有一些用于该http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/DateUtil.html的实用程序,特别是http://poi.apache.org/apidocs/org/apache/ poi/ss/usermodel/DateUtil.html#getJavaDate(double)

注意 Excel 将日期存储为自 1900 年以来的天数(加上小数天数)(在某些情况下,它可以从 1904 年开始)。请参阅http://support.microsoft.com/kb/180162

于 2013-09-26T12:29:30.297 回答
14
于 2018-10-30T05:59:12.217 回答
2

正如许多用户已经指出的那样,Excel 将日期和时间存储为一个数字,表示自1900 年 1 月 0日以来的天数,加上 24 小时一天的小数部分:ddddd.tttttt.
这称为序列日期序列日期时间

但这里的答案只代表了故事的一部分——除了指出现有库中准备使用的方法。

来自 Microsoft 的链接文档并没有使其更加清晰。

MS DATEVALUE 函数状态:

Excel 将日期存储为连续的序列号,以便可以在计算中使用它们。默认情况下,1900 年 1 月 1 日是序列号 1,而 2008 年 1 月 1 日是序列号 39448,因为它是 1900 年 1 月 1 日之后的 39,447 天

好吧,我要检查一下这个声明:

LocalDate testDate = LocalDate.of(1900, Month.JANUARY, 1).plusDays(39447);
System.out.println(testDate);// prints 2008-01-02

1900 年 1 月 1日之后的 39,447 天确实是…… 2008 年 1 月 2 日

这是为什么?

Excel 中的日期由从一个纪元(1899 年 12 月 30 日或 1900 年 1 月 1 日或 1904 年......)开始的天数表示,这只是故事的一部分。

我在这里找到了最终答案:Excel 中的日期和时间(某个上帝或任何可能祝福这些人的人)。

在 Excel 中实现日期例程的开发人员故意引入了一个错误,以便与Lotus 1-2-3中的相同已知问题兼容。

他们将 1900 年视为闰年,但事实并非如此,因此任何超过 1900 年 1 月 28 日的日期都比实际日期多一天。

这就是 Excel 认为2008 年 1 月 1 日由数字 39448 表示的原因:因为它是1900 年 1 月 0 日之后的 39,448个单位(是的,Excel 认为是) - 即39,447 天加上1900 年 1 月 29 日

Excel 还可以将序列日期的日期部分视为自 1904 年 1 月 0 日以来的天数;此模式称为1904 模式1904 系统,用于与 Macintosh 系统兼容。

由于 Excel 日期不携带任何时区信息——它只是一个数字——最好使用 Java 类(如LocalDate/ LocalDateTime)来表示没有时区信息的此类值。

好吧,在实践中——对于现在的日期——人们可能会认为 Excel 时代从1900 年 12 月 30 日开始,但事实并非如此。


Excel 演示- 日期格式为dd/mm/yyyy

7
日期作为左侧的数字插入


适合所需转换的类:

public class SerialDate {

    //days from 1899-12-31 to Instant.EPOCH (1970-01-01T00:00:00Z)
    public static final long EPOCH = -25568L;
    private long serialDays;
    private double serialTime;
    private long epochDays;
    private long daySeconds;

    /**
     * @param date number of Excel-days since <i>January 0, 1899</i>
     */
    public SerialDate(long date) {
        serialDays = date;
        if (date > 59)//Lotus123 bug
            --date;
        epochDays = EPOCH + date;
    }
            
    /**
     * @param date number of days since <i>January 0, 1899</i> with a time fraction
     */
    public SerialDate(double date) {
        this((long)date);
        serialTime = date - serialDays;
        daySeconds = Math.round(serialTime * 24 * 60 * 60);
    }
            
    /**
     * @return days since 1970-01-01
     */
    public long toEpochDays() {
        return epochDays;
    }
            
    /**
     * @return seconds of the day for this SerialDate
     */
    public long toDaySeconds() {
        return daySeconds;
    }
            
    /**
     * @return a value suitable for an Excel date
     */
    public double getSerialDate() {
        return serialTime + serialDays;
    }
    
}

使用示例:

LocalDate dt = LocalDate.ofEpochDay(new SerialDate(41275).toEpochDays());
System.out.println(dt);//prints 2013-01-01

SerialDate sd = new SerialDate(33257.415972222225);
LocalDateTime dt = LocalDateTime.of(
        LocalDate.ofEpochDay(sd.toEpochDays()),
        LocalTime.ofSecondOfDay(sd.toDaySeconds()));
System.out.println(dt);//prints 1991-01-19T09:59
于 2020-12-17T23:05:42.653 回答
0

Excel 的序列化日期是自 1900 年 1 月 1 日以来的天数。为了再次计算出日期,我们必须添加序列号,相当于天数。

对于没有任何依赖关系的 Java 8

```

  /*

    1900-1-0            0
    1900-1-1            1
    1900-1-2            2
    1900-1-3            3


     */


    int days = 43323;
    LocalDate start = LocalDate.of(1900, 1, 1);
    LocalDate today = LocalDate.of(2018, 8, 11);


    // days to date
    LocalDate date = start.plusDays(days).minusDays(2);

    System.out.println(date);

    // date to days
    long days1 = ChronoUnit.DAYS.between(start, today) + 2;
    System.out.println(days1);

```

于 2018-08-11T12:31:22.817 回答