将Excel中的Date的数字表示转换为java中的Date

时间:2013-09-26 12:24:45

标签: java excel

我在excel中有日期列,但是当我在我的java应用程序中读取时,我正在获得数值

实施例

Excel日期

1/1/2013

我正在

41275.00

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

5 个答案:

答案 0 :(得分:14)

以下是如何将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

答案 1 :(得分:13)

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

答案 2 :(得分:3)

tl; dr

使用现代的 java.time 类。

LocalDate                                    // Represent a date-only vaule, without time-of-day and without time zone.
.of( 1899 , Month.DECEMBER , 30 )            // Specify epoch reference date used by *some* versions of Excel. Beware: Some versions use a 1904 epoch reference. Returns a `LocalDate` object.
.plusDays(                                   // Add a number of days. 
    (long) Double.parseDouble( "41275.00" )  // Get a number of whole days from your input string.
)                                            // Returns another instance of a `LocalDate`, per Immutable Objects pattern, rather than altering the original.        
.toString()                                  // Generate text representing the value of this `LocalDate` in standard ISO 8601 format.
  

2013-01-01

java.time

现代的解决方案使用 java.time 类取代了与最早的Java版本捆绑在一起的可怕的旧式日期时间类。

史诗参考日期:1899-12-30

根据this documentation,来自Microsoft Excel的值是自epoch reference中1900-01-01的UTC以来的天数。在内部,实际参考日期为this Wikipedia page中记录的1899年12月30日

请注意,Excel use a different epoch in 1904的某些版本(macOS的旧版本?)。

在代码中的某个地方建立纪元引用。

final static public LocalDate EXCEL_EPOCH_REFERENCE = 
    LocalDate.of( 1899 , Month.DECEMBER , 30 )
; // Beware: Some versions of Excel use a 1904 epoch reference.

做数学

将您的输入字符串解析为BigDecimal以确保准确性(相对于浮点类型,它们会折衷精度以提高执行速度)。

BigDecimal countFromEpoch = new BigDecimal( "41275.00" );

将整天数添加到纪元参考日期。

long days = countFromEpoch.longValue();  // Extract the number of whole days, dropping the fraction.
LocalDate localDate = EXCEL_EPOCH_REFERENCE.plusDays( days );
  

localDate.toString():2013年1月1日


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

答案 3 :(得分: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);

```

答案 4 :(得分:0)

这里的答案仅代表故事的一部分-除了指出现有库中的现成方法。

Microsoft的链接文档对此没有更加明确的说明。

MS DATEVALUE function状态:

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

我明白了!我将验证以下语句:

    function dec2bin(dec){
      return (dec >>> 0).toString(2).split('').reverse().join('');
    }

1900年1月1日之后的39447天,确实是... 2008年1月2日

为什么?

Excel中的日期由 epoch (1899年12月30日或1900年1月1日或1904年1月1日)开始的天数来表示这一事实只是其中一部分

我在这里找到了一个最终的答案:Dates And Times In Excel(某个上帝或任何可以祝福这些家伙的人)。

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

他们威胁将1900年定为a年,但这不是 , 因此任何超过1900年1月28日的日期都比实际日期多一天。

这就是为什么Excel认为 2008年1月1日用数字39448表示的原因:因为它是1900年1月0日之后的39447天(是的,Excel认为是零)-即39446天加上1月29日1900年。

由于Excel日期不包含任何时区信息,所以最好使用LocalDate / LocalDateTime之类的Java类来表示没有时区信息的此类值。

嗯,实际上-从现在开始-可能是从 1900年12月30日开始的Excel时代。


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

enter image description here
日期插入为左侧的数字


适合所需转换的类:

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