猿问

Java 将“Excel 日期序列号”转换为“DateTime”

如何使用 Java 将“excel 日期序列号”(即 33257.415972222225)转换为 DateTime(即 19/01/1991 09:59:00)?


凤凰求蛊
浏览 313回答 2
2回答

慕虎7371278

您还可以查看Apache POI的Source code , method DateUtils#getLocalDateTime(double date, boolean use1904windowing, boolean roundSeconds)。这个实用程序类提供了更方便的方法来处理 Excel 日期。

白板的微信

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-021900 年 1 月 1日之后的 39,447 天确实是…… 2008 年 1 月 2 日!这是为什么?Excel 中的日期由从一个纪元(1899 年 12 月 30 日或 1900 年 1 月 1 日或 1904 年...)开始的天数表示这一事实只是故事的一部分。我在这里找到了一个终极答案:Excel 中的日期和时间(上帝或谁可以祝福这些人)。在 Excel 中实现日期例程的开发人员故意引入了一个错误,以便与Lotus 1-2-3 中的相同已知问题兼容。他们将 1900 年视为闰年,但事实并非如此,因此任何超过 1900 年 2 月 28 日的日期都比实际日期多一天。这就是为什么 Excel 认为2008 年 1 月 1 日由数字 39448 表示的原因:因为它是1900 年 1 月 0 日之后的39,448 个单位(是的,Excel 认为是零)——即39,447 天加上1900 年 2 月 29 日。Excel 还可以将序列日期的日期部分视为自 1904 年 1 月 0 日以来的天数;此模式称为1904 模式或1904 系统,用于与 Macintosh 系统兼容。由于 Excel 日期不携带任何时区信息 - 它只是一个数字 - 最好使用像LocalDate/LocalDateTime这样的Java 类来表示没有时区信息的此类值。好吧,在实践中 - 对于现在的日期 - 人们可能认为 Excel 纪元从1900 年 12 月 30 日开始,但事实并非如此。Excel 演示- 日期格式为dd/mm/yyyy hh:MM:ss日期作为左边的数字插入适合所需转换的类:public class SerialDate {&nbsp; &nbsp; //days from 1899-12-31 to Instant.EPOCH (1970-01-01T00:00:00Z)&nbsp; &nbsp; public static final long EPOCH = -25568L;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; private long serialDays;&nbsp; &nbsp; private double serialTime;&nbsp; &nbsp; private long epochDays;&nbsp; &nbsp; private long daySeconds;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* @param date number of Excel-days since <i>January 0, 1899</i>&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; public SerialDate(long date) {&nbsp; &nbsp; &nbsp; &nbsp; serialDays = date;&nbsp; &nbsp; &nbsp; &nbsp; if (date > 59)//Lotus123 bug&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; --date;&nbsp; &nbsp; &nbsp; &nbsp; epochDays = EPOCH + date;&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* @param date number of days since <i>January 0, 1899</i> with a time fraction&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; public SerialDate(double date) {&nbsp; &nbsp; &nbsp; &nbsp; this((long)date);&nbsp; &nbsp; &nbsp; &nbsp; serialTime = date - serialDays;&nbsp; &nbsp; &nbsp; &nbsp; daySeconds = Math.round(serialTime * 24 * 60 * 60);&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* @return days since 1970-01-01&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; public long toEpochDays() {&nbsp; &nbsp; &nbsp; &nbsp; return epochDays;&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* @return seconds of the day for this SerialDate&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; public long toDaySeconds() {&nbsp; &nbsp; &nbsp; &nbsp; return daySeconds;&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* @return a value suitable for an Excel date&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; public double getSerialDate() {&nbsp; &nbsp; &nbsp; &nbsp; return serialTime + serialDays;&nbsp; &nbsp; }}用法示例:SerialDate sd = new SerialDate(33257.415972222225);LocalDateTime dt = LocalDateTime.of(&nbsp; &nbsp; &nbsp; &nbsp; LocalDate.ofEpochDay(sd.toEpochDays()),&nbsp; &nbsp; &nbsp; &nbsp; LocalTime.ofSecondOfDay(sd.toDaySeconds()));System.out.println(dt);//prints 1991-01-19T09:59
随时随地看视频慕课网APP

相关分类

Java
我要回答