/* * ----------------------------------------------------------------------- * Copyright © 2013-2016 Meno Hochschild, <http://www.menodata.de/> * ----------------------------------------------------------------------- * This file (JdkZoneProviderSPI.java) is part of project Time4J. * * Time4J is free software: You can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 2.1 of the License, or * (at your option) any later version. * * Time4J is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Time4J. If not, see <http://www.gnu.org/licenses/>. * ----------------------------------------------------------------------- */ package net.time4j.tz.threeten; import net.time4j.Month; import net.time4j.PlainTime; import net.time4j.TemporalType; import net.time4j.Weekday; import net.time4j.tz.TransitionHistory; import net.time4j.tz.ZonalOffset; import net.time4j.tz.ZonalTransition; import net.time4j.tz.ZoneModelProvider; import net.time4j.tz.model.DaylightSavingRule; import net.time4j.tz.model.GregorianTimezoneRule; import net.time4j.tz.model.OffsetIndicator; import net.time4j.tz.model.TransitionModel; import java.time.DayOfWeek; import java.time.Instant; import java.time.ZoneId; import java.time.zone.ZoneOffsetTransition; import java.time.zone.ZoneOffsetTransitionRule; import java.time.zone.ZoneRules; import java.time.zone.ZoneRulesException; import java.time.zone.ZoneRulesProvider; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; /** * <p>SPI-implementation for the indirect evaluation of "tzdb.dat"-repository * via the new zone-api in Java-8. </p> * * @author Meno Hochschild * @since 4.0 */ public class JdkZoneProviderSPI implements ZoneModelProvider { //~ Instanzvariablen -------------------------------------------------- private final String version; //~ Konstruktoren ----------------------------------------------------- public JdkZoneProviderSPI() { super(); this.version = ZoneRulesProvider.getVersions("America/New_York").lastEntry().getKey(); } //~ Methoden ---------------------------------------------------------- @Override public Set<String> getAvailableIDs() { return Collections.unmodifiableSet(ZoneRulesProvider.getAvailableZoneIds()); } @Override public Map<String, String> getAliases() { return Collections.emptyMap(); } @Override public String getFallback() { return ""; } @Override public String getName() { return "TZDB"; } @Override public String getLocation() { return "{java.home}/lib/tzdb.dat"; } @Override public String getVersion() { return this.version; } @Override public TransitionHistory load(String zoneID) { try { ZoneRules zoneRules = ZoneId.of(zoneID).getRules(); ZonalOffset initialOffset = ZonalOffset.ofTotalSeconds(zoneRules.getOffset(Instant.MIN).getTotalSeconds()); List<ZonalTransition> transitions = new ArrayList<>(); List<DaylightSavingRule> rules = new ArrayList<>(); for (ZoneOffsetTransition zot : zoneRules.getTransitions()) { Instant instant = zot.getInstant(); long posixTime = instant.getEpochSecond(); int previousOffset = zot.getOffsetBefore().getTotalSeconds(); int totalOffset = zot.getOffsetAfter().getTotalSeconds(); int dst = Math.toIntExact(zoneRules.getDaylightSavings(instant).getSeconds()); transitions.add(new ZonalTransition(posixTime, previousOffset, totalOffset, dst)); } for (ZoneOffsetTransitionRule zotr : zoneRules.getTransitionRules()) { DaylightSavingRule rule; int dom = zotr.getDayOfMonthIndicator(); // -28 bis +31 (ohne 0) DayOfWeek dayOfWeek = zotr.getDayOfWeek(); Month month = Month.valueOf(zotr.getMonth().getValue()); PlainTime timeOfDay = ( zotr.isMidnightEndOfDay() ? PlainTime.midnightAtEndOfDay() : TemporalType.LOCAL_TIME.translate(zotr.getLocalTime())); OffsetIndicator indicator; switch (zotr.getTimeDefinition()) { case STANDARD: indicator = OffsetIndicator.STANDARD_TIME; break; case UTC: indicator = OffsetIndicator.UTC_TIME; break; case WALL: indicator = OffsetIndicator.WALL_TIME; break; default: throw new UnsupportedOperationException(zotr.getTimeDefinition().name()); } int dst = (zotr.getOffsetAfter().getTotalSeconds() - zotr.getStandardOffset().getTotalSeconds()); if (dayOfWeek == null) { rule = GregorianTimezoneRule.ofFixedDay(month, dom, timeOfDay, indicator, dst); } else { Weekday wd = Weekday.valueOf(dayOfWeek.getValue()); if (dom == -1) { rule = GregorianTimezoneRule.ofLastWeekday(month, wd, timeOfDay, indicator, dst); } else if (dom < 0) { rule = new NegativeDayOfMonthPattern(month, dom, wd, timeOfDay, indicator, dst); } else { rule = GregorianTimezoneRule.ofWeekdayAfterDate(month, dom, wd, timeOfDay, indicator, dst); } } rules.add(rule); } return TransitionModel.of(initialOffset, transitions, rules); } catch (ZoneRulesException ex) { throw new IllegalArgumentException(ex); } } }