Преобразование из Excel datetime в ZonedDateTime

#excel #java-time #zoneddatetime #excel-dates

#excel #java-время #zoneddatetime #excel-даты

Вопрос:

Дата-время в Excel сохраняется как количество дней, прошедших с 1900-01-01 ( 1, поскольку, по его мнению, произошло 1900-02-29). Дробь в числе — это смещение по времени в сутках.

Это число не имеет понятия о часовых поясах. Таким образом, 12.5 — это 1900-01-12T12:00:00 в часовом поясе, в котором открыта ваша электронная таблица. Откройте его в Colorado, и он покажет полдень. Откройте его в Германии, и он показывает полдень. Это не мгновение, это LocalDateTime.

Для нашей системы, где мы храним все как OffsetDateTime или ZonedDateTime (в зависимости от того, как datetime было передано нам), логично, я думаю, создать ZonedDateTime из этого.

Что приводит к вопросу, как мне создать ZonedDateTime, присвоенный этому номеру Excel datetime, в местном часовом поясе?

Комментарии:

1. Вы могли бы сохранить datetime как UDT, возможно, в скрытом столбце, и использовать UDF, который извлекает смещение часового пояса из региональных настроек системы отдельных компьютеров, чтобы произвести корректировку.

2. Это может содержать некоторую полезную информацию superuser.com/questions/763996 /…

Ответ №1:

     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);
  

На моем компьютере выводится:

1900-01-12T12:00 01:00[Европа / Копенгаген]

Поскольку java.time использует только целые числа, я использую его самую высокую степень детализации, наносекунды. Это приведет к переполнению a long в 2192 году, поэтому для решения, рассчитанного на будущее, вы можете рассмотреть возможность добавления целых дней отдельно и преобразования только доли в nanos.