我有一个需要在 java 中读取的 Excel 表中的数据,我能够读取普通字符串,但是当我尝试读取包含日期和时间的单元格时(28/5/2018 10:00)我只得到日期为 2018 年 5 月 28 日。
这是excel单元格
此代码为:2018 年 5 月 28 日
row.getCell(6).toString()
此代码引发异常:
row.getCell(6).getStringCellValue()
我怎样才能读懂时间?
如何正确读取日期?
最佳答案
tl;博士
row // Starting with a Poi `Row` object.
.getCell(6) // Extract a Poi `Cell` object.
.getDateCellValue() // Extract value from spreadsheet as a `java.util.Date` object. This terrible class is now legacy. Immediately convert to java.time.Instant as seen on next line.
.toInstant() // Convert from legacy `java.util.Date` class to modern `java.time.Instant`. Both represent a moment in UTC.
.atZone( // Adjusting from UTC to a time zone.
ZoneId.of( "Asia/Tokyo" ) // Specify a time zone to adjust from UTC (an offset of zero hours-minutes-seconds).
) // Returns a `ZonedDateTime` object. Same moment, different wall-clock time.
.toLocalDate() // Extract the date-only portion. Or call `toLocalTime` for the time-of-day portion.
细节
其他答案正确显示了如何获得
java.util.Date
目的。但是那个类(a)很糟糕,并且(b)现在是遗留的,几年前被现代 java.time 类所取代。您需要更进一步才能获得适当的解决方案。得到您的
java.util.Date
后目的:java.util.Date javaUtilDate = row.getCell(6).getDateCellValue() ;
……您在 UTC 有时间。不幸的是,按照建议调用
Date::toString
:row.getCell(6).getDateCellValue().toString()
…造成令人困惑的结果。该方法应用 JVM 当前的默认时区,从 UTC 调整到某个时区。这就造成了这个时区是
java.util.Date
的一部分的错觉。 ,但事实并非如此。这种行为意味着您的结果在运行时会有所不同,具体取决于当前的默认时区。请注意,不仅用户可以更改默认时区,而且在该 JVM 中运行的任何应用程序的任何线程中的任何代码也可以更改。对于可预测的结果,您应该指定所需/预期的时区。
为此,请立即转换您的
java.util.Date
替换它,Instant
类(class)。两者都代表 UTC 中的一个时刻。请注意添加到旧遗留类的新转换方法。Instant instant = javaUtilDate.toInstant() ;
指定 proper time zone name格式为
Continent/Region
,如 America/Montreal
, Africa/Casablanca
, 或 Pacific/Auckland
.切勿使用 2-4 个字母的缩写,例如 EST
或 IST
因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。ZoneId zoneId = ZoneId.of( "Africa/Tunis" ) ;
如果您想使用 JVM 当前的默认时区,请显式请求它,并作为参数传递。如果省略,代码会变得模棱两可,因为我们不确定您是否打算使用默认值,或者您是否像许多程序员一样没有意识到这个问题。
ZoneId zoneId = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
将该时区应用于您在 UTC 中的时刻。
ZonedDateTime zdt = instant.atZone( zoneId ) ;
结果
ZonedDateTime
对象表示与Instant
相同的时刻,时间线上的相同点.但它的挂钟时间已调整为特定地区(时区)人们使用的时间。您问:
How can I read the time?
How can I read the date correctly?
您可以使用
DateTimeFormatter
以您想要的任何格式打印其中一个或两个,甚至自动本地化为 Locale
中定义的人类语言和文化规范目的。或者,您可以将日期和时间值提取为单独的对象。
LocalDate localDate = zdt.toLocalDate() ;
LocalTime localTime = zdt.toLocalTime() ;
关于 java.time
java.time框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy日期时间类,例如
java.util.Date
, Calendar
, & SimpleDateFormat
.要了解更多信息,请参阅 Oracle Tutorial .并在 Stack Overflow 上搜索许多示例和解释。规范为 JSR 310 .
Joda-Time项目,现在在 maintenance mode , 建议迁移到 java.time类。
您可以直接与您的数据库交换 java.time 对象。使用 JDBC driver符合 JDBC 4.2或更晚。不需要字符串,不需要
java.sql.*
类。从哪里获得 java.time 类?
ThreeTen-Extra项目通过附加类扩展了 java.time。该项目是 future 可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如
Interval
, YearWeek
, YearQuarter
, 和 more .
关于java - 使用Apache POI从java中的excel表中读取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59439895/