Я не мог держать пальцы подальше от этого, это весело.Насколько я понял, вы не знаете, из какого часового пояса идут начальная и конечная строки, это может быть любой часовой пояс.Что мы можем сделать, кроме как попробовать их все по очереди?
String startDate = "2019-09-29T06:00:00.000Z";
String endDate = "2019-10-06T05:59:59.999Z";
LocalTime dayStart = LocalTime.MIN;
LocalTime dayEndEarliset = LocalTime.of(23, 59, 59);
Instant startInstant = Instant.parse(startDate);
Instant endInstant = Instant.parse(endDate);
// Just out of curiosity find candidate time zones
Set<ZoneId> candidateZones = ZoneId.getAvailableZoneIds()
.stream()
.map(ZoneId::of)
.filter(zid -> startInstant.atZone(zid).toLocalTime().equals(dayStart)
&& ! endInstant.atZone(zid).toLocalTime().isBefore(dayEndEarliset))
.collect(Collectors.toSet());
System.out.println("Potential time zones: " + candidateZones);
// Real work: find candidate date(s)
Set<LocalDate> candidateDates = ZoneId.getAvailableZoneIds()
.stream()
.map(ZoneId::of)
.filter(zid -> startInstant.atZone(zid).toLocalTime().equals(dayStart)
&& ! endInstant.atZone(zid).toLocalTime().isBefore(dayEndEarliset))
.map(zid -> startInstant.atZone(zid).toLocalDate())
.collect(Collectors.toSet());
if (candidateDates.isEmpty()) {
System.out.println("Cannot identify a date from the instants");
} else if (candidateDates.size() > 1) {
System.out.println("Ambiguous date, candidates are " + candidateDates);
} else {
System.out.println("The date is " + candidateDates.iterator().next());
}
Это печатает:
Potential time zones: [America/Inuvik, America/Yellowknife, America/Regina, America/Boise, SystemV/MST7MDT, America/El_Salvador, America/Costa_Rica, America/Shiprock, America/Guatemala, America/Denver, America/Belize, America/Swift_Current, America/Managua, Mexico/BajaSur, Canada/Mountain, America/Cambridge_Bay, Navajo, America/Chihuahua, America/Ojinaga, MST7MDT, Pacific/Galapagos, America/Mazatlan, US/Mountain, America/Edmonton, America/Tegucigalpa, Canada/Saskatchewan, Etc/GMT+6, SystemV/CST6]
The date is 2019-09-29
И да, Америка / Денвер входит в число возможных часовых поясов, как и ожидалось.Пока я нашел дату начала.Вы можете найти пару начальной и конечной даты аналогичным образом.Возможно, вы предпочтете старомодный цикл, а не потоковую операцию.
Однако дата не всегда будет однозначной.Давайте попробуем построить интервал в один день в часовом поясе Pacific / Pago_Pago.Это по смещению -11: 00.
ZoneId zone = ZoneId.of("Pacific/Pago_Pago");
LocalDate testDate = LocalDate.of(2019, Month.OCTOBER, 2);
String startDate = testDate.atStartOfDay(zone).toInstant().toString();
String endDate = testDate.atTime(LocalTime.of(23, 59, 59, 999_000_000))
.atZone(zone)
.toInstant()
.toString();
Теперь вывод программы:
Potential time zones: [Antarctica/McMurdo, Pacific/Niue, Pacific/Samoa, Pacific/Tongatapu, Pacific/Enderbury, Etc/GMT+11, NZ, Antarctica/South_Pole, Etc/GMT-13, Pacific/Pago_Pago, Pacific/Midway, Pacific/Fakaofo, US/Samoa, Pacific/Auckland]
Ambiguous date, candidates are [2019-10-03, 2019-10-02]
Это потому, что существуют также часовые пояса со смещением +13: 00.Мы можем сказать, что смещение должно быть либо -11: 00, либо +13: 00, но мы не можем сказать, какое из двух.Таким образом, выходят две даты.
Используйте полуоткрытые интервалы для времени
Я не был уверен, будет ли конец всегда в 23: 59: 59,999 вчасовой пояс, о котором идет речь, а иногда возможно 23: 59: 59.999999 или что-то еще.Также независимо от того, сколько десятичных дробей мы добавим, теоретически будут существовать моменты, которые находятся после этого времени окончания, но все еще в пределах той же даты.В коде я консервативно принимаю что-нибудь с 23:59:59 и позже как время окончания.Точка, чтобы полностью избежать сомнения: Используйте полуоткрытый интервал .Представьте начало интервала как 00:00:00, как вы уже делаете, и конец как 00:00:00 в дате после последней даты.И считайте дату начала включительно, а конец - эксклюзив .