Those pesky 24 minutes
So I've recently stumbled upon this strange behavior and it took me some time to figure it out, so I am sharing ;)
We have an excel file with time values inside - hours only, no date. Here is an example with single value:
Not to keep you waiting for long, the explanation is as follows:
- if apache poi method cell.getDateCellValue() reads time from excel, it writes it in a Date object, and since date is not provided - it is set by default to December the 31st 1899.
Turns out at that time Warsaw, and large part of Poland, was part of Russian Empire. The time zone was some weird random value - GMT+1:24 (it is similarly off today in e. g. India). If you manually change the date from 1899-12-31 to 1915-08-05 or later, the code starts magically to work.
But why 5th of August 1915? Wasn't it the middle of World War One? Turns out around that time German Empire conquered Warsaw from Russian hands and apparently they changed the time zone, which stayed more or less that way until today. And some said we would never need the stuff we learned in history class, ha!
We have an excel file with time values inside - hours only, no date. Here is an example with single value:
We want to read it in java and do something with it - for example we know the document was created somewhere in Poland, and it has times of teleconference meetings with United Kingdom. So let's say we want to convert the hours to London time and send it to somebody in London. What could be simpler? Let's just use excellent apache.poi library, simplest possible way is as follows:
import org.apache.poi.EncryptedDocumentException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.*; import java.io.File; import java.io.IOException; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Iterator; public class EntryPoint { public static final String SAMPLE_XLSX_FILE_PATH = "./datetest.xls"; public static void main(String[] args) throws EncryptedDocumentException, InvalidFormatException, IOException { Workbook workbook = WorkbookFactory.create(new File(SAMPLE_XLSX_FILE_PATH)); Sheet sheet = workbook.getSheetAt(0); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm:ss"); IteratorrowIterator = sheet.rowIterator(); while (rowIterator.hasNext()) { Row row = rowIterator.next(); Iterator
cellIterator = row.cellIterator(); while (cellIterator.hasNext()) { Cell cell = cellIterator.next(); Instant val = cell.getDateCellValue().toInstant(); ZonedDateTime origTimestamp = val.atZone(ZoneId.of("Europe/Warsaw")); System.out.println("Timestamp at Warsaw location: " + origTimestamp.format(formatter)); ZonedDateTime gmtTimestamp = val.atZone(ZoneId.of("GMT")); System.out.println("Timestamp at London location: " + gmtTimestamp.format(formatter)); } System.out.println(); } } } |
so here we have reading from excel, printing the hour in original time zone, and then printing it in target time zone (London). But... what is this?? The hour is off by exactly 24 minutes... Why, oh why!
Not to keep you waiting for long, the explanation is as follows:
- if apache poi method cell.getDateCellValue() reads time from excel, it writes it in a Date object, and since date is not provided - it is set by default to December the 31st 1899.
Turns out at that time Warsaw, and large part of Poland, was part of Russian Empire. The time zone was some weird random value - GMT+1:24 (it is similarly off today in e. g. India). If you manually change the date from 1899-12-31 to 1915-08-05 or later, the code starts magically to work.
But why 5th of August 1915? Wasn't it the middle of World War One? Turns out around that time German Empire conquered Warsaw from Russian hands and apparently they changed the time zone, which stayed more or less that way until today. And some said we would never need the stuff we learned in history class, ha!
Komentarze
Prześlij komentarz