我无法将手指从这个上移开,这很有趣。据我了解,您不知道开始和结束字符串来自哪个时区,它可能是任何时区。除了依次尝试所有这些,我们还能做什么?
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,就像您已经做的那样,在最后一个日期 after 的日期中将结束表示为 00:00:00。并将开始日期视为包含日期,并将结束日期视为不包含。