[英]Read data from excel sheet in java with Apache POI
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() ;
以Continent/Region
格式指定正确的时区名称,例如America/Montreal
、 Africa/Casablanca
或Pacific/Auckland
。 永远不要使用EST
或IST
等 2-4 个字母的缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
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
相同的时刻,时间线上的相同同时点。 但它的挂钟时间已调整为特定地区(时区)的人们使用的时间。
你问:
我怎样才能读懂时间?
如何正确读取日期?
您可以使用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);
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.