1c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer/* 2c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 3c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 5c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This code is free software; you can redistribute it and/or modify it 6c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * under the terms of the GNU General Public License version 2 only, as 7c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * published by the Free Software Foundation. Oracle designates this 8c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * particular file as subject to the "Classpath" exception as provided 9c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * by Oracle in the LICENSE file that accompanied this code. 10c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 11c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This code is distributed in the hope that it will be useful, but WITHOUT 12c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * version 2 for more details (a copy is included in the LICENSE file that 15c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * accompanied this code). 16c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 17c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * You should have received a copy of the GNU General Public License version 18c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 2 along with this work; if not, write to the Free Software Foundation, 19c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 21c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * or visit www.oracle.com if you need additional information or have any 23c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * questions. 24c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 25c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 26c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer/* 27c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This file is available under and governed by the GNU General Public 28c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * License version 2 only, as published by the Free Software Foundation. 29c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * However, the following notice accompanied the original version of this 30c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * file: 31c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 32c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos 33c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 34c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * All rights reserved. 35c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 36c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Redistribution and use in source and binary forms, with or without 37c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * modification, are permitted provided that the following conditions are met: 38c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 39c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * * Redistributions of source code must retain the above copyright notice, 40c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * this list of conditions and the following disclaimer. 41c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 42c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * * Redistributions in binary form must reproduce the above copyright notice, 43c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * this list of conditions and the following disclaimer in the documentation 44c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * and/or other materials provided with the distribution. 45c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 46c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * * Neither the name of JSR-310 nor the names of its contributors 47c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * may be used to endorse or promote products derived from this software 48c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * without specific prior written permission. 49c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 50c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 51c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 52c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 53c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 54c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 55c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 56c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 57c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 58c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 59c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 60c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 62c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerpackage java.time; 63c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 64c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.io.DataOutput; 65c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.io.IOException; 66c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.io.InvalidObjectException; 67c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.io.ObjectInputStream; 68c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.io.Serializable; 69c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.time.format.DateTimeFormatterBuilder; 70c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.time.format.TextStyle; 71c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.time.temporal.TemporalAccessor; 72c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.time.temporal.TemporalField; 73c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.time.temporal.TemporalQueries; 74c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.time.temporal.TemporalQuery; 75c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.time.temporal.UnsupportedTemporalTypeException; 76c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.time.zone.ZoneRules; 77c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.time.zone.ZoneRulesException; 78c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.time.zone.ZoneRulesProvider; 79c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.util.Collections; 80c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.util.HashMap; 81c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.util.Locale; 82c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.util.Map; 83c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.util.Objects; 84c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.util.Set; 85c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerimport java.util.TimeZone; 86c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 87fa84287e36805c14f8177d449207b9701faacd10Przemyslaw Szczepaniak// Android-changed: removed ValueBased paragraph. 8815e65ec4e1ae555e9f487ab11a2e95d7ffbdc4a8Przemyslaw Szczepaniak// Android-changed: removed {@link ZoneRulesProvider}. 89c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer/** 90c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * A time-zone ID, such as {@code Europe/Paris}. 91c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 92c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * A {@code ZoneId} is used to identify the rules used to convert between 93c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * an {@link Instant} and a {@link LocalDateTime}. 94c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * There are two distinct types of ID: 95c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <ul> 96c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>Fixed offsets - a fully resolved offset from UTC/Greenwich, that uses 97c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * the same offset for all local date-times 98c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>Geographical regions - an area where a specific set of rules for finding 99c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * the offset from UTC/Greenwich apply 100c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * </ul> 101c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Most fixed offsets are represented by {@link ZoneOffset}. 102c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Calling {@link #normalized()} on any {@code ZoneId} will ensure that a 103c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * fixed offset ID will be represented as a {@code ZoneOffset}. 104c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 105c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The actual rules, describing when and how the offset changes, are defined by {@link ZoneRules}. 106c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This class is simply an ID used to obtain the underlying rules. 107c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This approach is taken because rules are defined by governments and change 108c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * frequently, whereas the ID is stable. 109c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 110c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The distinction has other effects. Serializing the {@code ZoneId} will only send 111c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * the ID, whereas serializing the rules sends the entire data set. 112c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Similarly, a comparison of two IDs only examines the ID, whereas 113c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * a comparison of two rules examines the entire data set. 114c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 115c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <h3>Time-zone IDs</h3> 116c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The ID is unique within the system. 117c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * There are three types of ID. 118c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 119c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The simplest type of ID is that from {@code ZoneOffset}. 120c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This consists of 'Z' and IDs starting with '+' or '-'. 121c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 122c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The next type of ID are offset-style IDs with some form of prefix, 123c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * such as 'GMT+2' or 'UTC+01:00'. 124c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The recognised prefixes are 'UTC', 'GMT' and 'UT'. 125c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The offset is the suffix and will be normalized during creation. 126c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * These IDs can be normalized to a {@code ZoneOffset} using {@code normalized()}. 127c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 128c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The third type of ID are region-based IDs. A region-based ID must be of 129c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * two or more characters, and not start with 'UTC', 'GMT', 'UT' '+' or '-'. 13015e65ec4e1ae555e9f487ab11a2e95d7ffbdc4a8Przemyslaw Szczepaniak * Region-based IDs are defined by configuration. 131c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The configuration focuses on providing the lookup from the ID to the 132c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * underlying {@code ZoneRules}. 133c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 134c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Time-zone rules are defined by governments and change frequently. 135c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * There are a number of organizations, known here as groups, that monitor 136c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * time-zone changes and collate them. 137c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The default group is the IANA Time Zone Database (TZDB). 138c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Other organizations include IATA (the airline industry body) and Microsoft. 139c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 140c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Each group defines its own format for the region ID it provides. 141c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The TZDB group defines IDs such as 'Europe/London' or 'America/New_York'. 142c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * TZDB IDs take precedence over other groups. 143c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 144c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * It is strongly recommended that the group name is included in all IDs supplied by 145c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * groups other than TZDB to avoid conflicts. For example, IATA airline time-zone 146c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * region IDs are typically the same as the three letter airport code. 147c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * However, the airport of Utrecht has the code 'UTC', which is obviously a conflict. 148c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The recommended format for region IDs from groups other than TZDB is 'group~region'. 149c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Thus if IATA data were defined, Utrecht airport would be 'IATA~UTC'. 150c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 151c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <h3>Serialization</h3> 152c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This class can be serialized and stores the string zone ID in the external form. 153c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The {@code ZoneOffset} subclass uses a dedicated format that only stores the 154c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * offset from UTC/Greenwich. 155c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 156c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * A {@code ZoneId} can be deserialized in a Java Runtime where the ID is unknown. 157c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * For example, if a server-side Java Runtime has been updated with a new zone ID, but 158c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * the client-side Java Runtime has not been updated. In this case, the {@code ZoneId} 159c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * object will exist, and can be queried using {@code getId}, {@code equals}, 160c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * {@code hashCode}, {@code toString}, {@code getDisplayName} and {@code normalized}. 161c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * However, any call to {@code getRules} will fail with {@code ZoneRulesException}. 162c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This approach is designed to allow a {@link ZonedDateTime} to be loaded and 163c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * queried, but not modified, on a Java Runtime with incomplete time-zone information. 164c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 165c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @implSpec 166c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This abstract class has two implementations, both of which are immutable and thread-safe. 167c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * One implementation models region-based IDs, the other is {@code ZoneOffset} modelling 168c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * offset-based IDs. This difference is visible in serialization. 169c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 170c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @since 1.8 171c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 172c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauerpublic abstract class ZoneId implements Serializable { 173c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 174c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 175c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * A map of zone overrides to enable the short time-zone names to be used. 176c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 177c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Use of short zone IDs has been deprecated in {@code java.util.TimeZone}. 178c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This map allows the IDs to continue to be used via the 179c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * {@link #of(String, Map)} factory method. 180c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 181c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This map contains a mapping of the IDs that is in line with TZDB 2005r and 182c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * later, where 'EST', 'MST' and 'HST' map to IDs which do not include daylight 183c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * savings. 184c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 185c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This maps as follows: 186c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <ul> 187c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>EST - -05:00</li> 188c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>HST - -10:00</li> 189c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>MST - -07:00</li> 190c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>ACT - Australia/Darwin</li> 191c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>AET - Australia/Sydney</li> 192c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>AGT - America/Argentina/Buenos_Aires</li> 193c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>ART - Africa/Cairo</li> 194c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>AST - America/Anchorage</li> 195c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>BET - America/Sao_Paulo</li> 196c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>BST - Asia/Dhaka</li> 197c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>CAT - Africa/Harare</li> 198c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>CNT - America/St_Johns</li> 199c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>CST - America/Chicago</li> 200c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>CTT - Asia/Shanghai</li> 201c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>EAT - Africa/Addis_Ababa</li> 202c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>ECT - Europe/Paris</li> 203c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>IET - America/Indiana/Indianapolis</li> 204c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>IST - Asia/Kolkata</li> 205c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>JST - Asia/Tokyo</li> 206c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>MIT - Pacific/Apia</li> 207c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>NET - Asia/Yerevan</li> 208c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>NST - Pacific/Auckland</li> 209c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>PLT - Asia/Karachi</li> 210c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>PNT - America/Phoenix</li> 211c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>PRT - America/Puerto_Rico</li> 212c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>PST - America/Los_Angeles</li> 213c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>SST - Pacific/Guadalcanal</li> 214c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>VST - Asia/Ho_Chi_Minh</li> 215c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * </ul> 216c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The map is unmodifiable. 217c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 218c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public static final Map<String, String> SHORT_IDS; 219c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer static { 220c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer Map<String, String> map = new HashMap<>(64); 221c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("ACT", "Australia/Darwin"); 222c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("AET", "Australia/Sydney"); 223c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("AGT", "America/Argentina/Buenos_Aires"); 224c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("ART", "Africa/Cairo"); 225c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("AST", "America/Anchorage"); 226c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("BET", "America/Sao_Paulo"); 227c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("BST", "Asia/Dhaka"); 228c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("CAT", "Africa/Harare"); 229c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("CNT", "America/St_Johns"); 230c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("CST", "America/Chicago"); 231c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("CTT", "Asia/Shanghai"); 232c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("EAT", "Africa/Addis_Ababa"); 233c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("ECT", "Europe/Paris"); 234c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("IET", "America/Indiana/Indianapolis"); 235c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("IST", "Asia/Kolkata"); 236c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("JST", "Asia/Tokyo"); 237c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("MIT", "Pacific/Apia"); 238c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("NET", "Asia/Yerevan"); 239c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("NST", "Pacific/Auckland"); 240c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("PLT", "Asia/Karachi"); 241c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("PNT", "America/Phoenix"); 242c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("PRT", "America/Puerto_Rico"); 243c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("PST", "America/Los_Angeles"); 244c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("SST", "Pacific/Guadalcanal"); 245c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("VST", "Asia/Ho_Chi_Minh"); 246c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("EST", "-05:00"); 247c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("MST", "-07:00"); 248c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer map.put("HST", "-10:00"); 249c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer SHORT_IDS = Collections.unmodifiableMap(map); 250c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 251c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 252c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Serialization version. 253c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 254c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer private static final long serialVersionUID = 8352817235686L; 255c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 256c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer //----------------------------------------------------------------------- 257c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 258c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Gets the system default time-zone. 259c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 260c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This queries {@link TimeZone#getDefault()} to find the default time-zone 261c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * and converts it to a {@code ZoneId}. If the system default time-zone is changed, 262c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * then the result of this method will also change. 263c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 264c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the zone ID, not null 265c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws DateTimeException if the converted zone ID has an invalid format 266c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws ZoneRulesException if the converted zone region ID cannot be found 267c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 268c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public static ZoneId systemDefault() { 269c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return TimeZone.getDefault().toZoneId(); 270c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 271c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 272c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 273c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Gets the set of available zone IDs. 274c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 275c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This set includes the string form of all available region-based IDs. 276c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Offset-based zone IDs are not included in the returned set. 277c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The ID can be passed to {@link #of(String)} to create a {@code ZoneId}. 278c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 279c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The set of zone IDs can increase over time, although in a typical application 280c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * the set of IDs is fixed. Each call to this method is thread-safe. 281c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 282c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return a modifiable copy of the set of zone IDs, not null 283c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 284c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public static Set<String> getAvailableZoneIds() { 285c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return ZoneRulesProvider.getAvailableZoneIds(); 286c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 287c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 288c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer //----------------------------------------------------------------------- 289c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 290c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Obtains an instance of {@code ZoneId} using its ID using a map 291c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * of aliases to supplement the standard zone IDs. 292c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 293c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Many users of time-zones use short abbreviations, such as PST for 294c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 'Pacific Standard Time' and PDT for 'Pacific Daylight Time'. 295c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * These abbreviations are not unique, and so cannot be used as IDs. 296c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This method allows a map of string to time-zone to be setup and reused 297c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * within an application. 298c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 299c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param zoneId the time-zone ID, not null 300c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param aliasMap a map of alias zone IDs (typically abbreviations) to real zone IDs, not null 301c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the zone ID, not null 302c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws DateTimeException if the zone ID has an invalid format 303c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws ZoneRulesException if the zone ID is a region ID that cannot be found 304c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 305c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public static ZoneId of(String zoneId, Map<String, String> aliasMap) { 306c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer Objects.requireNonNull(zoneId, "zoneId"); 307c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer Objects.requireNonNull(aliasMap, "aliasMap"); 308c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer String id = aliasMap.get(zoneId); 309c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer id = (id != null ? id : zoneId); 310c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return of(id); 311c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 312c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 313c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 314c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Obtains an instance of {@code ZoneId} from an ID ensuring that the 315c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * ID is valid and available for use. 316c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 317c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This method parses the ID producing a {@code ZoneId} or {@code ZoneOffset}. 318c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * A {@code ZoneOffset} is returned if the ID is 'Z', or starts with '+' or '-'. 319c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The result will always be a valid ID for which {@link ZoneRules} can be obtained. 320c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 321c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Parsing matches the zone ID step by step as follows. 322c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <ul> 323c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>If the zone ID equals 'Z', the result is {@code ZoneOffset.UTC}. 324c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>If the zone ID consists of a single letter, the zone ID is invalid 325c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * and {@code DateTimeException} is thrown. 326c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>If the zone ID starts with '+' or '-', the ID is parsed as a 327c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * {@code ZoneOffset} using {@link ZoneOffset#of(String)}. 328c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>If the zone ID equals 'GMT', 'UTC' or 'UT' then the result is a {@code ZoneId} 329c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * with the same ID and rules equivalent to {@code ZoneOffset.UTC}. 330c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>If the zone ID starts with 'UTC+', 'UTC-', 'GMT+', 'GMT-', 'UT+' or 'UT-' 331c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * then the ID is a prefixed offset-based ID. The ID is split in two, with 332c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * a two or three letter prefix and a suffix starting with the sign. 333c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The suffix is parsed as a {@link ZoneOffset#of(String) ZoneOffset}. 334c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The result will be a {@code ZoneId} with the specified UTC/GMT/UT prefix 335c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * and the normalized offset ID as per {@link ZoneOffset#getId()}. 336c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The rules of the returned {@code ZoneId} will be equivalent to the 337c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * parsed {@code ZoneOffset}. 338c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <li>All other IDs are parsed as region-based zone IDs. Region IDs must 339c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * match the regular expression <code>[A-Za-z][A-Za-z0-9~/._+-]+</code> 340c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * otherwise a {@code DateTimeException} is thrown. If the zone ID is not 341c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * in the configured set of IDs, {@code ZoneRulesException} is thrown. 342c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The detailed format of the region ID depends on the group supplying the data. 343c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The default set of data is supplied by the IANA Time Zone Database (TZDB). 344c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This has region IDs of the form '{area}/{city}', such as 'Europe/Paris' or 'America/New_York'. 345c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This is compatible with most IDs from {@link java.util.TimeZone}. 346c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * </ul> 347c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 348c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param zoneId the time-zone ID, not null 349c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the zone ID, not null 350c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws DateTimeException if the zone ID has an invalid format 351c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws ZoneRulesException if the zone ID is a region ID that cannot be found 352c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 353c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public static ZoneId of(String zoneId) { 354c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return of(zoneId, true); 355c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 356c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 357c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 358c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Obtains an instance of {@code ZoneId} wrapping an offset. 359c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 360c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * If the prefix is "GMT", "UTC", or "UT" a {@code ZoneId} 361c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * with the prefix and the non-zero offset is returned. 362c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * If the prefix is empty {@code ""} the {@code ZoneOffset} is returned. 363c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 364c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param prefix the time-zone ID, not null 365c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param offset the offset, not null 366c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the zone ID, not null 367c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws IllegalArgumentException if the prefix is not one of 368c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * "GMT", "UTC", or "UT", or "" 369c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 370c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public static ZoneId ofOffset(String prefix, ZoneOffset offset) { 371c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer Objects.requireNonNull(prefix, "prefix"); 372c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer Objects.requireNonNull(offset, "offset"); 373c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (prefix.length() == 0) { 374c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return offset; 375c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 376c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 377c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (!prefix.equals("GMT") && !prefix.equals("UTC") && !prefix.equals("UT")) { 378c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer throw new IllegalArgumentException("prefix should be GMT, UTC or UT, is: " + prefix); 379c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 380c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 381c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (offset.getTotalSeconds() != 0) { 382c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer prefix = prefix.concat(offset.getId()); 383c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 384c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return new ZoneRegion(prefix, offset.getRules()); 385c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 386c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 387c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 388c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Parses the ID, taking a flag to indicate whether {@code ZoneRulesException} 389c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * should be thrown or not, used in deserialization. 390c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 391c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param zoneId the time-zone ID, not null 392c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param checkAvailable whether to check if the zone ID is available 393c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the zone ID, not null 394c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws DateTimeException if the ID format is invalid 395c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws ZoneRulesException if checking availability and the ID cannot be found 396c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 397c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer static ZoneId of(String zoneId, boolean checkAvailable) { 398c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer Objects.requireNonNull(zoneId, "zoneId"); 399c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (zoneId.length() <= 1 || zoneId.startsWith("+") || zoneId.startsWith("-")) { 400c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return ZoneOffset.of(zoneId); 401c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } else if (zoneId.startsWith("UTC") || zoneId.startsWith("GMT")) { 402c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return ofWithPrefix(zoneId, 3, checkAvailable); 403c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } else if (zoneId.startsWith("UT")) { 404c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return ofWithPrefix(zoneId, 2, checkAvailable); 405c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 406c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return ZoneRegion.ofId(zoneId, checkAvailable); 407c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 408c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 409c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 410c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Parse once a prefix is established. 411c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 412c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param zoneId the time-zone ID, not null 413c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param prefixLength the length of the prefix, 2 or 3 414c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the zone ID, not null 415c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws DateTimeException if the zone ID has an invalid format 416c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 417c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer private static ZoneId ofWithPrefix(String zoneId, int prefixLength, boolean checkAvailable) { 418c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer String prefix = zoneId.substring(0, prefixLength); 419c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (zoneId.length() == prefixLength) { 420c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return ofOffset(prefix, ZoneOffset.UTC); 421c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 422c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (zoneId.charAt(prefixLength) != '+' && zoneId.charAt(prefixLength) != '-') { 423c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return ZoneRegion.ofId(zoneId, checkAvailable); // drop through to ZoneRulesProvider 424c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 425c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer try { 426c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer ZoneOffset offset = ZoneOffset.of(zoneId.substring(prefixLength)); 427c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (offset == ZoneOffset.UTC) { 428c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return ofOffset(prefix, offset); 429c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 430c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return ofOffset(prefix, offset); 431c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } catch (DateTimeException ex) { 432c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer throw new DateTimeException("Invalid ID for offset-based ZoneId: " + zoneId, ex); 433c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 434c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 435c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 436c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer //----------------------------------------------------------------------- 437c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 438c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Obtains an instance of {@code ZoneId} from a temporal object. 439c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 440c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This obtains a zone based on the specified temporal. 441c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * A {@code TemporalAccessor} represents an arbitrary set of date and time information, 442c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * which this factory converts to an instance of {@code ZoneId}. 443c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 444c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * A {@code TemporalAccessor} represents some form of date and time information. 445c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This factory converts the arbitrary temporal object to an instance of {@code ZoneId}. 446c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 447c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The conversion will try to obtain the zone in a way that favours region-based 448c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * zones over offset-based zones using {@link TemporalQueries#zone()}. 449c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 450c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This method matches the signature of the functional interface {@link TemporalQuery} 451c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * allowing it to be used as a query via method reference, {@code ZoneId::from}. 452c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 453c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param temporal the temporal object to convert, not null 454c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the zone ID, not null 455c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws DateTimeException if unable to convert to a {@code ZoneId} 456c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 457c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public static ZoneId from(TemporalAccessor temporal) { 458c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer ZoneId obj = temporal.query(TemporalQueries.zone()); 459c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (obj == null) { 460c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer throw new DateTimeException("Unable to obtain ZoneId from TemporalAccessor: " + 461c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer temporal + " of type " + temporal.getClass().getName()); 462c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 463c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return obj; 464c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 465c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 466c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer //----------------------------------------------------------------------- 467c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 468c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Constructor only accessible within the package. 469c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 470c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer ZoneId() { 471c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (getClass() != ZoneOffset.class && getClass() != ZoneRegion.class) { 472c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer throw new AssertionError("Invalid subclass"); 473c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 474c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 475c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 476c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer //----------------------------------------------------------------------- 477c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 478c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Gets the unique time-zone ID. 479c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 480c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This ID uniquely defines this object. 481c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The format of an offset based ID is defined by {@link ZoneOffset#getId()}. 482c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 483c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the time-zone unique ID, not null 484c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 485c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public abstract String getId(); 486c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 487c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer //----------------------------------------------------------------------- 488c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 489c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Gets the textual representation of the zone, such as 'British Time' or 490c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * '+02:00'. 491c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 492c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * This returns the textual name used to identify the time-zone ID, 493c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * suitable for presentation to the user. 494c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The parameters control the style of the returned text and the locale. 495c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 496c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * If no textual mapping is found then the {@link #getId() full ID} is returned. 497c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 498c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param style the length of the text required, not null 499c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param locale the locale to use, not null 500c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the text value of the zone, not null 501c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 502c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public String getDisplayName(TextStyle style, Locale locale) { 503c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return new DateTimeFormatterBuilder().appendZoneText(style).toFormatter(locale).format(toTemporal()); 504c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 505c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 506c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 507c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Converts this zone to a {@code TemporalAccessor}. 508c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 509c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * A {@code ZoneId} can be fully represented as a {@code TemporalAccessor}. 510c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * However, the interface is not implemented by this class as most of the 511c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * methods on the interface have no meaning to {@code ZoneId}. 512c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 513c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The returned temporal has no supported fields, with the query method 514c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * supporting the return of the zone using {@link TemporalQueries#zoneId()}. 515c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 516c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return a temporal equivalent to this zone, not null 517c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 518c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer private TemporalAccessor toTemporal() { 519c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return new TemporalAccessor() { 520c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer @Override 521c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public boolean isSupported(TemporalField field) { 522c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return false; 523c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 524c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer @Override 525c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public long getLong(TemporalField field) { 526c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 527c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 528c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer @SuppressWarnings("unchecked") 529c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer @Override 530c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public <R> R query(TemporalQuery<R> query) { 531c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (query == TemporalQueries.zoneId()) { 532c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return (R) ZoneId.this; 533c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 534c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return TemporalAccessor.super.query(query); 535c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 536c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer }; 537c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 538c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 539c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer //----------------------------------------------------------------------- 54015e65ec4e1ae555e9f487ab11a2e95d7ffbdc4a8Przemyslaw Szczepaniak // Android-removed: ZoneRulesProvider related paragraph 541c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 542c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Gets the time-zone rules for this ID allowing calculations to be performed. 543c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 544c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The rules provide the functionality associated with a time-zone, 545c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * such as finding the offset for a given instant or local date-time. 546c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 547c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * A time-zone can be invalid if it is deserialized in a Java Runtime which 548c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * does not have the same rules loaded as the Java Runtime that stored it. 549c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * In this case, calling this method will throw a {@code ZoneRulesException}. 550c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 551c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * {@link ZoneOffset} will always return a set of rules where the offset never changes. 552c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 553c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the rules, not null 554c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws ZoneRulesException if no rules are available for this ID 555c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 556c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public abstract ZoneRules getRules(); 557c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 558c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 559c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Normalizes the time-zone ID, returning a {@code ZoneOffset} where possible. 560c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 561c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The returns a normalized {@code ZoneId} that can be used in place of this ID. 562c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The result will have {@code ZoneRules} equivalent to those returned by this object, 563c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * however the ID returned by {@code getId()} may be different. 564c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 565c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The normalization checks if the rules of this {@code ZoneId} have a fixed offset. 566c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * If they do, then the {@code ZoneOffset} equal to that offset is returned. 567c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Otherwise {@code this} is returned. 568c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 569c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the time-zone unique ID, not null 570c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 571c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public ZoneId normalized() { 572c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer try { 573c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer ZoneRules rules = getRules(); 574c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (rules.isFixedOffset()) { 575c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return rules.getOffset(Instant.EPOCH); 576c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 577c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } catch (ZoneRulesException ex) { 578c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer // invalid ZoneRegion is not important to this method 579c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 580c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return this; 581c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 582c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 583c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer //----------------------------------------------------------------------- 584c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 585c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Checks if this time-zone ID is equal to another time-zone ID. 586c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 587c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * The comparison is based on the ID. 588c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 589c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param obj the object to check, null returns false 590c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return true if this is equal to the other time-zone ID 591c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 592c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer @Override 593c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public boolean equals(Object obj) { 594c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (this == obj) { 595c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return true; 596c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 597c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer if (obj instanceof ZoneId) { 598c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer ZoneId other = (ZoneId) obj; 599c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return getId().equals(other.getId()); 600c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 601c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return false; 602c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 603c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 604c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 605c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * A hash code for this time-zone ID. 606c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 607c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return a suitable hash code 608c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 609c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer @Override 610c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public int hashCode() { 611c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return getId().hashCode(); 612c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 613c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 614c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer //----------------------------------------------------------------------- 615c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 616c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Defend against malicious streams. 617c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 618c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @param s the stream to read 619c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @throws InvalidObjectException always 620c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 621c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer private void readObject(ObjectInputStream s) throws InvalidObjectException { 622c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer throw new InvalidObjectException("Deserialization via serialization delegate"); 623c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 624c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 625c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 626c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Outputs this zone as a {@code String}, using the ID. 627c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 628c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return a string representation of this time-zone ID, not null 629c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 630c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer @Override 631c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer public String toString() { 632c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return getId(); 633c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 634c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 635c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer //----------------------------------------------------------------------- 636c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer /** 637c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * Writes the object using a 638c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <a href="../../serialized-form.html#java.time.Ser">dedicated serialized form</a>. 639c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @serialData 640c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <pre> 641c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * out.writeByte(7); // identifies a ZoneId (not ZoneOffset) 642c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * out.writeUTF(getId()); 643c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * </pre> 644c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * <p> 645c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * When read back in, the {@code ZoneId} will be created as though using 646c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * {@link #of(String)}, but without any exception in the case where the 647c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * ID has a valid format, but is not in the known set of region-based IDs. 648c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * 649c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer * @return the instance of {@code Ser}, not null 650c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer */ 651c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer // this is here for serialization Javadoc 652c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer private Object writeReplace() { 653c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer return new Ser(Ser.ZONE_REGION_TYPE, this); 654c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer } 655c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 656c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer abstract void write(DataOutput out) throws IOException; 657c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer 658c9dd3385ea6f927052783f42fb1282fb093e636eJoachim Sauer} 659