A datetime in Excel is saved as the number of days since 1900-01-01 (+1 as it thinks 1900-02-29 occurred). The fraction in the number is the time offset in the day.
This number has no concept of timezones. So 12.5 is 1900-01-12T12:00:00 in the timezone you have your spreadsheet open in. Open it in Colorado and it shows noon. Open it in Germany and it shows noon. It's not an instant, it's a LocalDateTime.
For our system where we store everything as an OffsetDateTime or ZonedDateTime (depending on how the datetime was passed to us) the logical thing to do I think is create a ZonedDateTime from this.
Which leads to the question, how do I create a ZonedDateTime, set to this Excel datetime number, in the local time zone?
LocalDate msBaseDate = LocalDate.of(1899, Month.DECEMBER, 31);
double dateFromExcel = 12.5;
long nanosSinceBase = Math.round(dateFromExcel * TimeUnit.DAYS.toNanos(1));
ZonedDateTime dateTime = msBaseDate.atStartOfDay()
.plusNanos(nanosSinceBase)
.atZone(ZoneId.systemDefault());
System.out.println(dateTime);
On my computer the output is:
1900-01-12T12:00+01:00[Europe/Copenhagen]
Since java.time only uses whole numbers, I am used its finest granularity, nanoseconds. This will overflow a long
in year 2192, so for a future-proof solution you may consider adding the whole days separately and only converting the fraction to nanos.