@Test public void testCompatibility() { Set<String> allZones = ZoneId.getAvailableZoneIds(); List<String> zoneList = new ArrayList<>(allZones); Collections.sort(zoneList); List<ZoneId> zones = new ArrayList<>(zoneList.size()); List<TimeZoneRulesImpl> zoneRules = new ArrayList<>(zoneList.size()); for (String z : zoneList) { ZoneId zone = ZoneId.of(z); zones.add(zone); zoneRules.add(new TimeZoneRulesImpl(zone.getRules())); } long micros = Dates.toMillis(1900, 1, 1, 0, 0); long deadline = Dates.toMillis(2115, 12, 31, 0, 0); while (micros < deadline) { int y = Dates.getYear(micros); boolean leap = Dates.isLeapYear(y); int m = Dates.getMonthOfYear(micros, y, leap); int d = Dates.getDayOfMonth(micros, y, m, leap); LocalDateTime dt = LocalDateTime.of(y, m, d, 0, 0); for (int i = 0, n = zones.size(); i < n; i++) { ZoneId zone = zones.get(i); TimeZoneRulesImpl rules = zoneRules.get(i); ZonedDateTime zdt = dt.atZone(zone); long expected = zdt.getOffset().getTotalSeconds(); long changed = Dates.toMillis(zdt.getYear(), zdt.getMonthValue(), zdt.getDayOfMonth(), zdt.getHour(), zdt.getMinute()) + zdt.getSecond() * Dates.SECOND_MILLIS; expected += (changed - micros) / Dates.SECOND_MILLIS; long offset = rules.getOffset(micros, y, leap); try { Assert.assertEquals(expected, offset / Dates.SECOND_MILLIS); } catch (Throwable e) { System.out.println(zone.getId() + "; " + zdt + "; " + Dates.toString(micros + offset)); System.out.println("e: " + expected + "; a: " + offset); System.out.println(dt); System.out.println(Dates.toString(micros)); throw e; } } micros += Dates.DAY_MILLIS; } }
@Override public long getOffset(long millis, int year, boolean leap) { if (standardOffset != Long.MIN_VALUE) { return standardOffset; } if (ruleCount > 0 && millis > cutoffTransition) { return fromRules(millis, year, leap); } if (millis > cutoffTransition) { return lastWall; } return fromHistory(millis); }
TimeZoneRulesImpl implements TimeZoneRules { @Override public long getOffset(long millis, int year, boolean leap) { if (standardOffset != Long.MIN_VALUE) { return standardOffset; } if (ruleCount > 0 && millis > cutoffTransition) { return fromRules(millis, year, leap); } if (millis > cutoffTransition) { return lastWall; } return fromHistory(millis); } }
TimeZoneRulesImpl implements TimeZoneRules { @Override public long getOffset(long millis, int year, boolean leap) { if (standardOffset != Long.MIN_VALUE) { return standardOffset; } if (ruleCount > 0 && millis > cutoffTransition) { return fromRules(millis, year, leap); } if (millis > cutoffTransition) { return lastWall; } return fromHistory(millis); } TimeZoneRulesImpl(ZoneRules rules); }
TimeZoneRulesImpl implements TimeZoneRules { @Override public long getOffset(long millis, int year, boolean leap) { if (standardOffset != Long.MIN_VALUE) { return standardOffset; } if (ruleCount > 0 && millis > cutoffTransition) { return fromRules(millis, year, leap); } if (millis > cutoffTransition) { return lastWall; } return fromHistory(millis); } TimeZoneRulesImpl(ZoneRules rules); @Override long getOffset(long millis, int year, boolean leap); @Override long getOffset(long millis); }
TimeZoneRulesImpl implements TimeZoneRules { @Override public long getOffset(long millis, int year, boolean leap) { if (standardOffset != Long.MIN_VALUE) { return standardOffset; } if (ruleCount > 0 && millis > cutoffTransition) { return fromRules(millis, year, leap); } if (millis > cutoffTransition) { return lastWall; } return fromHistory(millis); } TimeZoneRulesImpl(ZoneRules rules); @Override long getOffset(long millis, int year, boolean leap); @Override long getOffset(long millis); static final long SAVING_INSTANT_TRANSITION; static final long STANDARD_OFFSETS; static final long LAST_RULES; static final long SAVINGS_LOCAL_TRANSITION; static final long WALL_OFFSETS; }