/* * ----------------------------------------------------------------------- * Copyright © 2013-2015 Meno Hochschild, <http://www.menodata.de/> * ----------------------------------------------------------------------- * This file (WindowsZone.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.other; import net.time4j.tz.TZID; import net.time4j.tz.spi.WinZoneProviderSPI; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; import java.util.Collections; import java.util.Locale; import java.util.Set; /** * <p>Represents a windows timezone name which can be mapped to an IANA/Olson-ID * using a territory information. </p> * * <p>Example: </p> * * <pre> * WindowsZone wzn = WindowsZone.of("Eastern Standard Time"); * TZID winzone = wzn.resolveSmart(Locale.US); * System.out.println(winzone.canonical()); * // output: WINDOWS~America/New_York * </pre> * * @author Meno Hochschild * @since 2.2 */ /*[deutsch] * <p>Repräsentiert eine Windows-Zeitzone, die mit Hilfe einer * Länderinformation zu einer IANA/Olson-ID umgeformt werden kann. </p> * * <p>Beispiel: </p> * * <pre> * WindowsZone wzn = WindowsZone.of("Eastern Standard Time"); * TZID winzone = wzn.resolveSmart(Locale.US); * System.out.println(winzone.canonical()); * // output: WINDOWS~America/New_York * </pre> * * @author Meno Hochschild * @since 2.2 */ public final class WindowsZone implements Comparable<WindowsZone>, Serializable { //~ Statische Felder/Initialisierungen -------------------------------- private static final long serialVersionUID = -6071278077083785308L; //~ Instanzvariablen -------------------------------------------------- /** * @serial name of windows zone */ private final String name; //~ Konstruktoren ----------------------------------------------------- private WindowsZone(String name) { super(); this.name = name; } //~ Methoden ---------------------------------------------------------- /** * <p>Yields all available names of windows zones. </p> * * @return unmodifiable set of zone names for Windows * @since 2.3 */ /*[deutsch] * <p>Liefert alle verfügbaren Namen von Windows-Zeitzonen. </p> * * @return unmodifiable set of zone names for Windows * @since 2.3 */ public static Set<String> getAvailableNames() { return WinZoneProviderSPI.NAME_BASED_MAP.keySet(); } /** * <p>Creates a name reference to a windows zone. </p> * * @param name standardized windows zone name * @return new instance of {@code WindowsZone} * @throws IllegalArgumentException if given name is not supported * @since 2.2 * @see #getAvailableNames() */ /*[deutsch] * <p>Erzeugt einen Namensbezug zu einer Windows-Zeitzone. </p> * * @param name standardized windows zone name * @return new instance of {@code WindowsZone} * @throws IllegalArgumentException if given name is not supported * @since 2.2 * @see #getAvailableNames() */ public static WindowsZone of(String name) { check(name); return new WindowsZone(name); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } else if (obj instanceof WindowsZone) { WindowsZone that = (WindowsZone) obj; return this.name.equals(that.name); } else { return false; } } @Override public int hashCode() { return this.name.hashCode(); } /** * <p>Returns the name of this windows zone reference. </p> * * @return name of windows zone */ /*[deutsch] * <p>Liefert den Namen dieser Zeitzonenreferenz. </p> * * @return name of windows zone */ @Override public String toString() { return this.name; } /** * <p>The natural order is based on the lexicographical order of the * underlying names of windows zones. </p> * * @param other another windows zone name reference * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. */ /*[deutsch] * <p>Die natürliche Ordnung basiert auf der lexikographischen * Reihenfolge der zugrundeliegenden Namen von Windows-Zeitzonen. </p> * * @param other another windows zone name reference * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. */ @Override public int compareTo(WindowsZone other) { return this.name.compareTo(other.name); } /** * <p>Resolves this name reference to a set of various zone ids for given * country. </p> * * @param country country reference * @return set of ids belonging to this windows zone * @since 2.2 */ /*[deutsch] * <p>Löst diese Namensreferenz zu einem Satz von Zonen-IDs zum * angegebenen Land auf. </p> * * @param country country reference * @return set of ids belonging to this windows zone * @since 2.2 */ public Set<TZID> resolve(Locale country) { Set<TZID> ids = WinZoneProviderSPI.NAME_BASED_MAP.get(this.name).get(country.getCountry()); if (ids == null) { return Collections.emptySet(); } else { return Collections.unmodifiableSet(ids); } } /** * <p>Resolves this name reference to at most one zone id for given * country. </p> * * <p>Normally windows zones cannot be resolved to one single zone id, * but there is usually one preferred zone id based on the fact that * the daylight saving rules for this name and given country are often * the same for all belonging zone ids in the recent past. This method * tries its best to yield a result but applications have to check if * the result is {@code null}. </p> * * @param country country reference * @return preferred zone id belonging to this windows zone * or {@code null} if given country is not related to this name * @since 2.2 */ /*[deutsch] * <p>Löst diese Namensreferenz zu maximal einer Zonen-ID zum * angegebenen Land auf. </p> * * <p>Normalerweise lassen sich Windows-Zeitzonen nicht zu einer eindeutigen * Zonen-ID auflösen, aber es gibt gewöhnlich eine bevorzugte * Zeitzonen-ID, deren Zeitumstellungsregeln sich in der jüngsten * Vergangenheit oft nicht von denen anderer Zeitzonen-IDs der gleichen * Windows-Zeitzone unterscheiden. Diese Methode versucht das Beste, um * eine solche bevorzugte Zeitzone zu ermitteln, aber Anwendungen sind * verpflichtet zu prüfen, ob das Ergebnis {@code null} ist. </p> * * @param country country reference * @return preferred zone id belonging to this windows zone * or {@code null} if given country is not related to this name * @since 2.2 */ public TZID resolveSmart(Locale country) { Set<TZID> ids = this.resolve(country); if (ids.size() > 1) { ids = WinZoneProviderSPI.NAME_BASED_MAP.get(this.name).get("001"); } switch (ids.size()) { case 0: return null; case 1: return ids.iterator().next(); default: throw new AssertionError( "Ambivalent windows zone: " + this.name); } } /** * <p>Yields the repository version. </p> * * @return String * @since 2.3 */ /*[deutsch] * <p>Liefert die zugrundeliegende Version der CLDR-Daten. </p> * * @return String * @since 2.3 */ static String getVersion() { return WinZoneProviderSPI.WIN_NAME_VERSION; } private static void check(String name) { if ( name.isEmpty() || !WinZoneProviderSPI.NAME_BASED_MAP.keySet().contains(name) ) { throw new IllegalArgumentException("Unknown windows zone: " + name); } } /** * @serialData Checks the consistency. * @param in object input stream * @throws ClassNotFoundException if the class of a serialized object could not be found. * @throws IOException if an I/O error occurs. * @throws IllegalArgumentException in case of inconsistencies */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); check(this.name); } }