java - 使用Apache POI从java中的excel表中读取数据

标签 java excel apache-poi

我有一个需要在 java 中读取的 Excel 表中的数据,我能够读取普通字符串,但是当我尝试读取包含日期和时间的单元格时(28/5/2018 10:00)我只得到日期为 2018 年 5 月 28 日。

这是excel单元格

enter image description here

此代码为:2018 年 5 月 28 日

enter image description here

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 个字母的缩写,例如 ESTIST因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
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() ;

Table of date-time types in Java, both modern and legacy

关于 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 类?
  • Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 , 和更高版本 - 标准 Java API 的一部分,具有捆绑的实现。
  • Java 9 添加了一些小功能和修复。
  • Java SE 6Java SE 7
  • 大多数 java.time 功能在 ThreeTen-Backport 中向后移植到 Java 6 和 7。 .
  • Android
  • java.time 类的更高版本的 Android 捆绑实现。
  • 对于早期的 Android (<26),ThreeTenABP项目适应ThreeTen-Backport (上文提到的)。见 How to use ThreeTenABP… .

  • ThreeTen-Extra项目通过附加类扩展了 java.time。该项目是 future 可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如 Interval , YearWeek , YearQuarter , 和 more .

    关于java - 使用Apache POI从java中的excel表中读取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59439895/

    相关文章:

    java - Nashorn 脚本引擎在 Java 8 SE 嵌入式上为空

    excel - 刷新 WorkbookConnection 或其 ODBCConnection 有什么区别吗?

    vba - 在 Select Case 中使用 InStr 函数

    java - 尽管我添加了正确的 Apache POI .jar 文件,Eclipse 仍抛出 ClassNotFoundException?

    java - 有没有办法使用 Apache POI 修改 Microsoft Word 页脚?

    javax.crypto.BadPaddingException : pad block corrupted

    java - 将 EditText 中的字符串转换为 Double

    Java 异常。将一种类型转换为另一种类型

    Excel VBA : Range gives Argument Not Optional error message

    java - 无法识别工作表时如何访问 XSSF 内容