[英]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.