以下是Excel单元格的截图:
https://istack.dev59.com/yPMLn.webp 这段代码读取的是:28-May-2018
https://istack.dev59.com/hbJJ2.webp
row.getCell(6).toString()
这段代码会抛出一个异常:
row.getCell(6).getStringCellValue()
我如何读取时间?
我如何正确阅读日期?
row.getCell(6).toString()
这段代码会抛出一个异常:
row.getCell(6).getStringCellValue()
我如何读取时间?
我如何正确阅读日期?
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
。两者都表示UTC中的一个时刻。请注意,旧的传统类中添加了新的转换方法。
Instant instant = javaUtilDate.toInstant() ;
请在格式为大陆/地区
的正确时区名称中指定时区,例如America/Montreal
、Africa/Casablanca
或Pacific/Auckland
。永远不要使用2-4个字母的缩写,如EST
或IST
,因为它们不是真正的标准化时区,也不是唯一的。
ZoneId zoneId = ZoneId.of( "Africa/Tunis" ) ;
ZoneId zoneId = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
ZonedDateTime zdt = instant.atZone( zoneId ) ;
ZonedDateTime
对象表示相同的时刻,时间轴上的同一点与Instant
相同。但其壁钟时间已调整为某个特定区域(时区)使用的时间。
你问:
如何读取时间?
如何正确读取日期?
您可以使用DateTimeFormatter
以任何所需格式打印任一项或两项,甚至自动本地化到在Locale
对象中定义的人类语言和文化规范。
或者您可以将日期和时间值提取为单独的对象。
LocalDate localDate = zdt.toLocalDate() ;
LocalTime localTime = zdt.toLocalTime() ;
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
要了解更多,请参见Oracle教程。并在Stack Overflow上搜索许多示例和说明。规范是JSR 310。
Joda-Time项目现在处于维护模式,建议迁移到java.time类。
您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。无需字符串,无需java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra 项目扩展了 java.time 的附加类。该项目是 java.time 可能未来添加内容的试验场所。您可能会在这里找到一些有用的类,例如 Interval
, YearWeek
, YearQuarter
和 更多。
请尝试
row.getCell(6).getDateCellValue();
如果您仍需要将其转换为字符串,请尝试以下方法:
row.getCell(6).getDateCellValue().toString();
希望这对你有所帮助
try (FileInputStream fis = new FileInputStream(filename)) {
HSSFWorkbook workbook = new HSSFWorkbook(fis);
HSSFSheet sheet = workbook.getSheetAt(0);
// Read a cell the first row and sixth cell.
HSSFCell cell = sheet.getRow(0).getCell(6);
// Using HSSFDateUtil to check if a cell contains a date.
if (HSSFDateUtil.isCellDateFormatted(cell)) {
System.out.println("The cell contains a date value: "
+ cell.getDateCellValue());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
如果要获取单元格的值,并以类似于 Excel
单元格中所显示的格式化字符串的形式进行操作,可以使用 DataFormatter。
示例:
...
DataFormatter formatter = new DataFormatter();
...
Row row = ...;
...
Cell cell = row.getCell(6);
String value = formatter.formatCellValue(cell);
System.out.println(value);
...
由于该值可能是公式的结果,因此请使用 DataFormatter
与 FormulaEvaluator 一起使用:
...
DataFormatter formatter = new DataFormatter();
...
Workbook workbook = ...;
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
...
Row row = ...;
...
Cell cell = row.getCell(6);
String value = formatter.formatCellValue(cell, evaluator);
System.out.println(value);
...
apache poi 4.1.1
版本提供了 java.time.LocalDateTime getLocalDateTimeCellValue() 方法。同时,还有 org.apache.poi.ss.usermodel.DataFormatter 可以使用与Excel
相同的格式将单元格内容作为格式化字符串获取。 - Axel Richter