我在excel中有日期列,但是当我在我的java应用程序中读取时,我正在获得数值
实施例
Excel日期
1/1/2013
我正在
41275.00
如何在我的Java应用程序中将数字转换为日期?
答案 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)
使用现代的 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版本捆绑在一起的可怕的旧式日期时间类。
根据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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
目前位于Joda-Time的maintenance 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中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。
答案 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
日期插入为左侧的数字
适合所需转换的类:
LocalDate testDate = LocalDate.of(1900, Month.JANUARY, 1).plusDays(39447);
System.out.println(testDate);// prints 2008-01-02