1 /*
   2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * This file is available under and governed by the GNU General Public
  26  * License version 2 only, as published by the Free Software Foundation.
  27  * However, the following notice accompanied the original version of this
  28  * file:
  29  *
  30  * Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
  31  *
  32  * All rights reserved.
  33  *
  34  * Redistribution and use in source and binary forms, with or without
  35  * modification, are permitted provided that the following conditions are met:
  36  *
  37  *  * Redistributions of source code must retain the above copyright notice,
  38  *    this list of conditions and the following disclaimer.
  39  *
  40  *  * Redistributions in binary form must reproduce the above copyright notice,
  41  *    this list of conditions and the following disclaimer in the documentation
  42  *    and/or other materials provided with the distribution.
  43  *
  44  *  * Neither the name of JSR-310 nor the names of its contributors
  45  *    may be used to endorse or promote products derived from this software
  46  *    without specific prior written permission.
  47  *
  48  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  49  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  50  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  51  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  52  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  53  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  54  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  55  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  56  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  57  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  58  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  59  */
  60 package tck.java.time.zone;
  61 
  62 import static org.testng.Assert.assertEquals;
  63 import static org.testng.Assert.assertFalse;
  64 import static org.testng.Assert.assertNotNull;
  65 import static org.testng.Assert.assertTrue;
  66 
  67 import java.io.ByteArrayInputStream;
  68 import java.io.ByteArrayOutputStream;
  69 import java.io.ObjectInputStream;
  70 import java.io.ObjectOutputStream;
  71 import java.util.Iterator;
  72 import java.util.List;
  73 
  74 import java.time.DayOfWeek;
  75 import java.time.Duration;
  76 import java.time.Instant;
  77 import java.time.LocalDate;
  78 import java.time.LocalDateTime;
  79 import java.time.LocalTime;
  80 import java.time.Month;
  81 import java.time.Year;
  82 import java.time.ZoneId;
  83 import java.time.ZoneOffset;
  84 import java.time.ZonedDateTime;
  85 import java.time.zone.ZoneOffsetTransition;
  86 import java.time.zone.ZoneOffsetTransitionRule;
  87 import java.time.zone.ZoneOffsetTransitionRule.TimeDefinition;
  88 import java.time.zone.ZoneRules;
  89 
  90 import org.testng.annotations.Test;
  91 
  92 /**
  93  * Test ZoneRules.
  94  */
  95 @Test
  96 public class TCKZoneRules {
  97 
  98     private static final ZoneOffset OFFSET_ZERO = ZoneOffset.ofHours(0);
  99     private static final ZoneOffset OFFSET_PONE = ZoneOffset.ofHours(1);
 100     private static final ZoneOffset OFFSET_PTWO = ZoneOffset.ofHours(2);
 101     public static final String LATEST_TZDB = "2009b";
 102     private static final int OVERLAP = 2;
 103     private static final int GAP = 0;
 104 
 105     //-----------------------------------------------------------------------
 106     // Basics
 107     //-----------------------------------------------------------------------
 108     public void test_serialization_loaded() throws Exception {
 109         assertSerialization(europeLondon());
 110         assertSerialization(europeParis());
 111         assertSerialization(americaNewYork());
 112     }
 113 
 114     private void assertSerialization(ZoneRules test) throws Exception {
 115         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 116         ObjectOutputStream out = new ObjectOutputStream(baos);
 117         out.writeObject(test);
 118         baos.close();
 119         byte[] bytes = baos.toByteArray();
 120 
 121         ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
 122         ObjectInputStream in = new ObjectInputStream(bais);
 123         ZoneRules result = (ZoneRules) in.readObject();
 124 
 125         assertEquals(result, test);
 126     }
 127 
 128     //-----------------------------------------------------------------------
 129     // Europe/London
 130     //-----------------------------------------------------------------------
 131     private ZoneRules europeLondon() {
 132         return ZoneId.of("Europe/London").getRules();
 133     }
 134 
 135     public void test_London() {
 136         ZoneRules test = europeLondon();
 137         assertEquals(test.isFixedOffset(), false);
 138     }
 139 
 140     public void test_London_preTimeZones() {
 141         ZoneRules test = europeLondon();
 142         ZonedDateTime old = createZDT(1800, 1, 1, ZoneOffset.UTC);
 143         Instant instant = old.toInstant();
 144         ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(0, -1, -15);
 145         assertEquals(test.getOffset(instant), offset);
 146         checkOffset(test, old.toLocalDateTime(), offset, 1);
 147         assertEquals(test.getStandardOffset(instant), offset);
 148         assertEquals(test.getDaylightSavings(instant), Duration.ZERO);
 149         assertEquals(test.isDaylightSavings(instant), false);
 150     }
 151 
 152     public void test_London_getOffset() {
 153         ZoneRules test = europeLondon();
 154         assertEquals(test.getOffset(createInstant(2008, 1, 1, ZoneOffset.UTC)), OFFSET_ZERO);
 155         assertEquals(test.getOffset(createInstant(2008, 2, 1, ZoneOffset.UTC)), OFFSET_ZERO);
 156         assertEquals(test.getOffset(createInstant(2008, 3, 1, ZoneOffset.UTC)), OFFSET_ZERO);
 157         assertEquals(test.getOffset(createInstant(2008, 4, 1, ZoneOffset.UTC)), OFFSET_PONE);
 158         assertEquals(test.getOffset(createInstant(2008, 5, 1, ZoneOffset.UTC)), OFFSET_PONE);
 159         assertEquals(test.getOffset(createInstant(2008, 6, 1, ZoneOffset.UTC)), OFFSET_PONE);
 160         assertEquals(test.getOffset(createInstant(2008, 7, 1, ZoneOffset.UTC)), OFFSET_PONE);
 161         assertEquals(test.getOffset(createInstant(2008, 8, 1, ZoneOffset.UTC)), OFFSET_PONE);
 162         assertEquals(test.getOffset(createInstant(2008, 9, 1, ZoneOffset.UTC)), OFFSET_PONE);
 163         assertEquals(test.getOffset(createInstant(2008, 10, 1, ZoneOffset.UTC)), OFFSET_PONE);
 164         assertEquals(test.getOffset(createInstant(2008, 11, 1, ZoneOffset.UTC)), OFFSET_ZERO);
 165         assertEquals(test.getOffset(createInstant(2008, 12, 1, ZoneOffset.UTC)), OFFSET_ZERO);
 166     }
 167 
 168     public void test_London_getOffset_toDST() {
 169         ZoneRules test = europeLondon();
 170         assertEquals(test.getOffset(createInstant(2008, 3, 24, ZoneOffset.UTC)), OFFSET_ZERO);
 171         assertEquals(test.getOffset(createInstant(2008, 3, 25, ZoneOffset.UTC)), OFFSET_ZERO);
 172         assertEquals(test.getOffset(createInstant(2008, 3, 26, ZoneOffset.UTC)), OFFSET_ZERO);
 173         assertEquals(test.getOffset(createInstant(2008, 3, 27, ZoneOffset.UTC)), OFFSET_ZERO);
 174         assertEquals(test.getOffset(createInstant(2008, 3, 28, ZoneOffset.UTC)), OFFSET_ZERO);
 175         assertEquals(test.getOffset(createInstant(2008, 3, 29, ZoneOffset.UTC)), OFFSET_ZERO);
 176         assertEquals(test.getOffset(createInstant(2008, 3, 30, ZoneOffset.UTC)), OFFSET_ZERO);
 177         assertEquals(test.getOffset(createInstant(2008, 3, 31, ZoneOffset.UTC)), OFFSET_PONE);
 178         // cutover at 01:00Z
 179         assertEquals(test.getOffset(createInstant(2008, 3, 30, 0, 59, 59, 999999999, ZoneOffset.UTC)), OFFSET_ZERO);
 180         assertEquals(test.getOffset(createInstant(2008, 3, 30, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_PONE);
 181     }
 182 
 183     public void test_London_getOffset_fromDST() {
 184         ZoneRules test = europeLondon();
 185         assertEquals(test.getOffset(createInstant(2008, 10, 24, ZoneOffset.UTC)), OFFSET_PONE);
 186         assertEquals(test.getOffset(createInstant(2008, 10, 25, ZoneOffset.UTC)), OFFSET_PONE);
 187         assertEquals(test.getOffset(createInstant(2008, 10, 26, ZoneOffset.UTC)), OFFSET_PONE);
 188         assertEquals(test.getOffset(createInstant(2008, 10, 27, ZoneOffset.UTC)), OFFSET_ZERO);
 189         assertEquals(test.getOffset(createInstant(2008, 10, 28, ZoneOffset.UTC)), OFFSET_ZERO);
 190         assertEquals(test.getOffset(createInstant(2008, 10, 29, ZoneOffset.UTC)), OFFSET_ZERO);
 191         assertEquals(test.getOffset(createInstant(2008, 10, 30, ZoneOffset.UTC)), OFFSET_ZERO);
 192         assertEquals(test.getOffset(createInstant(2008, 10, 31, ZoneOffset.UTC)), OFFSET_ZERO);
 193         // cutover at 01:00Z
 194         assertEquals(test.getOffset(createInstant(2008, 10, 26, 0, 59, 59, 999999999, ZoneOffset.UTC)), OFFSET_PONE);
 195         assertEquals(test.getOffset(createInstant(2008, 10, 26, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_ZERO);
 196     }
 197 
 198     public void test_London_getOffsetInfo() {
 199         ZoneRules test = europeLondon();
 200         checkOffset(test, createLDT(2008, 1, 1), OFFSET_ZERO, 1);
 201         checkOffset(test, createLDT(2008, 2, 1), OFFSET_ZERO, 1);
 202         checkOffset(test, createLDT(2008, 3, 1), OFFSET_ZERO, 1);
 203         checkOffset(test, createLDT(2008, 4, 1), OFFSET_PONE, 1);
 204         checkOffset(test, createLDT(2008, 5, 1), OFFSET_PONE, 1);
 205         checkOffset(test, createLDT(2008, 6, 1), OFFSET_PONE, 1);
 206         checkOffset(test, createLDT(2008, 7, 1), OFFSET_PONE, 1);
 207         checkOffset(test, createLDT(2008, 8, 1), OFFSET_PONE, 1);
 208         checkOffset(test, createLDT(2008, 9, 1), OFFSET_PONE, 1);
 209         checkOffset(test, createLDT(2008, 10, 1), OFFSET_PONE, 1);
 210         checkOffset(test, createLDT(2008, 11, 1), OFFSET_ZERO, 1);
 211         checkOffset(test, createLDT(2008, 12, 1), OFFSET_ZERO, 1);
 212     }
 213 
 214     public void test_London_getOffsetInfo_toDST() {
 215         ZoneRules test = europeLondon();
 216         checkOffset(test, createLDT(2008, 3, 24), OFFSET_ZERO, 1);
 217         checkOffset(test, createLDT(2008, 3, 25), OFFSET_ZERO, 1);
 218         checkOffset(test, createLDT(2008, 3, 26), OFFSET_ZERO, 1);
 219         checkOffset(test, createLDT(2008, 3, 27), OFFSET_ZERO, 1);
 220         checkOffset(test, createLDT(2008, 3, 28), OFFSET_ZERO, 1);
 221         checkOffset(test, createLDT(2008, 3, 29), OFFSET_ZERO, 1);
 222         checkOffset(test, createLDT(2008, 3, 30), OFFSET_ZERO, 1);
 223         checkOffset(test, createLDT(2008, 3, 31), OFFSET_PONE, 1);
 224         // cutover at 01:00Z
 225         checkOffset(test, LocalDateTime.of(2008, 3, 30, 0, 59, 59, 999999999), OFFSET_ZERO, 1);
 226         checkOffset(test, LocalDateTime.of(2008, 3, 30, 2, 0, 0, 0), OFFSET_PONE, 1);
 227     }
 228 
 229     public void test_London_getOffsetInfo_fromDST() {
 230         ZoneRules test = europeLondon();
 231         checkOffset(test, createLDT(2008, 10, 24), OFFSET_PONE, 1);
 232         checkOffset(test, createLDT(2008, 10, 25), OFFSET_PONE, 1);
 233         checkOffset(test, createLDT(2008, 10, 26), OFFSET_PONE, 1);
 234         checkOffset(test, createLDT(2008, 10, 27), OFFSET_ZERO, 1);
 235         checkOffset(test, createLDT(2008, 10, 28), OFFSET_ZERO, 1);
 236         checkOffset(test, createLDT(2008, 10, 29), OFFSET_ZERO, 1);
 237         checkOffset(test, createLDT(2008, 10, 30), OFFSET_ZERO, 1);
 238         checkOffset(test, createLDT(2008, 10, 31), OFFSET_ZERO, 1);
 239         // cutover at 01:00Z
 240         checkOffset(test, LocalDateTime.of(2008, 10, 26, 0, 59, 59, 999999999), OFFSET_PONE, 1);
 241         checkOffset(test, LocalDateTime.of(2008, 10, 26, 2, 0, 0, 0), OFFSET_ZERO, 1);
 242     }
 243 
 244     public void test_London_getOffsetInfo_gap() {
 245         ZoneRules test = europeLondon();
 246         final LocalDateTime dateTime = LocalDateTime.of(2008, 3, 30, 1, 0, 0, 0);
 247         ZoneOffsetTransition trans = checkOffset(test, dateTime, OFFSET_ZERO, GAP);
 248         assertEquals(trans.isGap(), true);
 249         assertEquals(trans.isOverlap(), false);
 250         assertEquals(trans.getOffsetBefore(), OFFSET_ZERO);
 251         assertEquals(trans.getOffsetAfter(), OFFSET_PONE);
 252         assertEquals(trans.getInstant(), createInstant(2008, 3, 30, 1, 0, ZoneOffset.UTC));
 253         assertEquals(trans.getDateTimeBefore(), LocalDateTime.of(2008, 3, 30, 1, 0));
 254         assertEquals(trans.getDateTimeAfter(), LocalDateTime.of(2008, 3, 30, 2, 0));
 255         assertEquals(trans.isValidOffset(OFFSET_ZERO), false);
 256         assertEquals(trans.isValidOffset(OFFSET_PONE), false);
 257         assertEquals(trans.isValidOffset(OFFSET_PTWO), false);
 258         assertEquals(trans.toString(), "Transition[Gap at 2008-03-30T01:00Z to +01:00]");
 259 
 260         assertFalse(trans.equals(null));
 261         assertFalse(trans.equals(OFFSET_ZERO));
 262         assertTrue(trans.equals(trans));
 263 
 264         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
 265         assertTrue(trans.equals(otherTrans));
 266         assertEquals(trans.hashCode(), otherTrans.hashCode());
 267     }
 268 
 269     public void test_London_getOffsetInfo_overlap() {
 270         ZoneRules test = europeLondon();
 271         final LocalDateTime dateTime = LocalDateTime.of(2008, 10, 26, 1, 0, 0, 0);
 272         ZoneOffsetTransition trans = checkOffset(test, dateTime, OFFSET_PONE, OVERLAP);
 273         assertEquals(trans.isGap(), false);
 274         assertEquals(trans.isOverlap(), true);
 275         assertEquals(trans.getOffsetBefore(), OFFSET_PONE);
 276         assertEquals(trans.getOffsetAfter(), OFFSET_ZERO);
 277         assertEquals(trans.getInstant(), createInstant(2008, 10, 26, 1, 0, ZoneOffset.UTC));
 278         assertEquals(trans.getDateTimeBefore(), LocalDateTime.of(2008, 10, 26, 2, 0));
 279         assertEquals(trans.getDateTimeAfter(), LocalDateTime.of(2008, 10, 26, 1, 0));
 280         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-1)), false);
 281         assertEquals(trans.isValidOffset(OFFSET_ZERO), true);
 282         assertEquals(trans.isValidOffset(OFFSET_PONE), true);
 283         assertEquals(trans.isValidOffset(OFFSET_PTWO), false);
 284         assertEquals(trans.toString(), "Transition[Overlap at 2008-10-26T02:00+01:00 to Z]");
 285 
 286         assertFalse(trans.equals(null));
 287         assertFalse(trans.equals(OFFSET_PONE));
 288         assertTrue(trans.equals(trans));
 289 
 290         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
 291         assertTrue(trans.equals(otherTrans));
 292         assertEquals(trans.hashCode(), otherTrans.hashCode());
 293     }
 294 
 295     public void test_London_getStandardOffset() {
 296         ZoneRules test = europeLondon();
 297         ZonedDateTime zdt = createZDT(1840, 1, 1, ZoneOffset.UTC);
 298         while (zdt.getYear() < 2010) {
 299             Instant instant = zdt.toInstant();
 300             if (zdt.getYear() < 1848) {
 301                 assertEquals(test.getStandardOffset(instant), ZoneOffset.ofHoursMinutesSeconds(0, -1, -15));
 302             } else if (zdt.getYear() >= 1969 && zdt.getYear() < 1972) {
 303                 assertEquals(test.getStandardOffset(instant), OFFSET_PONE);
 304             } else {
 305                 assertEquals(test.getStandardOffset(instant), OFFSET_ZERO);
 306             }
 307             zdt = zdt.plusMonths(6);
 308         }
 309     }
 310 
 311     public void test_London_getTransitions() {
 312         ZoneRules test = europeLondon();
 313         List<ZoneOffsetTransition> trans = test.getTransitions();
 314 
 315         ZoneOffsetTransition first = trans.get(0);
 316         assertEquals(first.getDateTimeBefore(), LocalDateTime.of(1847, 12, 1, 0, 0));
 317         assertEquals(first.getOffsetBefore(), ZoneOffset.ofHoursMinutesSeconds(0, -1, -15));
 318         assertEquals(first.getOffsetAfter(), OFFSET_ZERO);
 319 
 320         ZoneOffsetTransition spring1916 = trans.get(1);
 321         assertEquals(spring1916.getDateTimeBefore(), LocalDateTime.of(1916, 5, 21, 2, 0));
 322         assertEquals(spring1916.getOffsetBefore(), OFFSET_ZERO);
 323         assertEquals(spring1916.getOffsetAfter(), OFFSET_PONE);
 324 
 325         ZoneOffsetTransition autumn1916 = trans.get(2);
 326         assertEquals(autumn1916.getDateTimeBefore(), LocalDateTime.of(1916, 10, 1, 3, 0));
 327         assertEquals(autumn1916.getOffsetBefore(), OFFSET_PONE);
 328         assertEquals(autumn1916.getOffsetAfter(), OFFSET_ZERO);
 329 
 330         ZoneOffsetTransition zot = null;
 331         Iterator<ZoneOffsetTransition> it = trans.iterator();
 332         while (it.hasNext()) {
 333             zot = it.next();
 334             if (zot.getDateTimeBefore().getYear() == 1990) {
 335                 break;
 336             }
 337         }
 338         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1990, 3, 25, 1, 0));
 339         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
 340         zot = it.next();
 341         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1990, 10, 28, 2, 0));
 342         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
 343         zot = it.next();
 344         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1991, 3, 31, 1, 0));
 345         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
 346         zot = it.next();
 347         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1991, 10, 27, 2, 0));
 348         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
 349         zot = it.next();
 350         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1992, 3, 29, 1, 0));
 351         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
 352         zot = it.next();
 353         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1992, 10, 25, 2, 0));
 354         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
 355         zot = it.next();
 356         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1993, 3, 28, 1, 0));
 357         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
 358         zot = it.next();
 359         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1993, 10, 24, 2, 0));
 360         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
 361         zot = it.next();
 362         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1994, 3, 27, 1, 0));
 363         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
 364         zot = it.next();
 365         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1994, 10, 23, 2, 0));
 366         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
 367         zot = it.next();
 368         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1995, 3, 26, 1, 0));
 369         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
 370         zot = it.next();
 371         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1995, 10, 22, 2, 0));
 372         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
 373         zot = it.next();
 374         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1996, 3, 31, 1, 0));
 375         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
 376         zot = it.next();
 377         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1996, 10, 27, 2, 0));
 378         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
 379         zot = it.next();
 380         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1997, 3, 30, 1, 0));
 381         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
 382         zot = it.next();
 383         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1997, 10, 26, 2, 0));
 384         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
 385         assertEquals(it.hasNext(), false);
 386     }
 387 
 388     public void test_London_getTransitionRules() {
 389         ZoneRules test = europeLondon();
 390         List<ZoneOffsetTransitionRule> rules = test.getTransitionRules();
 391         assertEquals(rules.size(), 2);
 392 
 393         ZoneOffsetTransitionRule in = rules.get(0);
 394         assertEquals(in.getMonth(), Month.MARCH);
 395         assertEquals(in.getDayOfMonthIndicator(), 25);  // optimized from -1
 396         assertEquals(in.getDayOfWeek(), DayOfWeek.SUNDAY);
 397         assertEquals(in.getLocalTime(), LocalTime.of(1, 0));
 398         assertEquals(in.getTimeDefinition(), TimeDefinition.UTC);
 399         assertEquals(in.getStandardOffset(), OFFSET_ZERO);
 400         assertEquals(in.getOffsetBefore(), OFFSET_ZERO);
 401         assertEquals(in.getOffsetAfter(), OFFSET_PONE);
 402 
 403         ZoneOffsetTransitionRule out = rules.get(1);
 404         assertEquals(out.getMonth(), Month.OCTOBER);
 405         assertEquals(out.getDayOfMonthIndicator(), 25);  // optimized from -1
 406         assertEquals(out.getDayOfWeek(), DayOfWeek.SUNDAY);
 407         assertEquals(out.getLocalTime(), LocalTime.of(1, 0));
 408         assertEquals(out.getTimeDefinition(), TimeDefinition.UTC);
 409         assertEquals(out.getStandardOffset(), OFFSET_ZERO);
 410         assertEquals(out.getOffsetBefore(), OFFSET_PONE);
 411         assertEquals(out.getOffsetAfter(), OFFSET_ZERO);
 412     }
 413 
 414     //-----------------------------------------------------------------------
 415     public void test_London_nextTransition_historic() {
 416         ZoneRules test = europeLondon();
 417         List<ZoneOffsetTransition> trans = test.getTransitions();
 418 
 419         ZoneOffsetTransition first = trans.get(0);
 420         assertEquals(test.nextTransition(first.getInstant().minusNanos(1)), first);
 421 
 422         for (int i = 0; i < trans.size() - 1; i++) {
 423             ZoneOffsetTransition cur = trans.get(i);
 424             ZoneOffsetTransition next = trans.get(i + 1);
 425 
 426             assertEquals(test.nextTransition(cur.getInstant()), next);
 427             assertEquals(test.nextTransition(next.getInstant().minusNanos(1)), next);
 428         }
 429     }
 430 
 431     public void test_London_nextTransition_rulesBased() {
 432         ZoneRules test = europeLondon();
 433         List<ZoneOffsetTransitionRule> rules = test.getTransitionRules();
 434         List<ZoneOffsetTransition> trans = test.getTransitions();
 435 
 436         ZoneOffsetTransition last = trans.get(trans.size() - 1);
 437         assertEquals(test.nextTransition(last.getInstant()), rules.get(0).createTransition(1998));
 438 
 439         for (int year = 1998; year < 2010; year++) {
 440             ZoneOffsetTransition a = rules.get(0).createTransition(year);
 441             ZoneOffsetTransition b = rules.get(1).createTransition(year);
 442             ZoneOffsetTransition c = rules.get(0).createTransition(year + 1);
 443 
 444             assertEquals(test.nextTransition(a.getInstant()), b);
 445             assertEquals(test.nextTransition(b.getInstant().minusNanos(1)), b);
 446 
 447             assertEquals(test.nextTransition(b.getInstant()), c);
 448             assertEquals(test.nextTransition(c.getInstant().minusNanos(1)), c);
 449         }
 450     }
 451 
 452     public void test_London_nextTransition_lastYear() {
 453         ZoneRules test = europeLondon();
 454         List<ZoneOffsetTransitionRule> rules = test.getTransitionRules();
 455         ZoneOffsetTransition zot = rules.get(1).createTransition(Year.MAX_VALUE);
 456         assertEquals(test.nextTransition(zot.getInstant()), null);
 457     }
 458 
 459     //-----------------------------------------------------------------------
 460     public void test_London_previousTransition_historic() {
 461         ZoneRules test = europeLondon();
 462         List<ZoneOffsetTransition> trans = test.getTransitions();
 463 
 464         ZoneOffsetTransition first = trans.get(0);
 465         assertEquals(test.previousTransition(first.getInstant()), null);
 466         assertEquals(test.previousTransition(first.getInstant().minusNanos(1)), null);
 467 
 468         for (int i = 0; i < trans.size() - 1; i++) {
 469             ZoneOffsetTransition prev = trans.get(i);
 470             ZoneOffsetTransition cur = trans.get(i + 1);
 471 
 472             assertEquals(test.previousTransition(cur.getInstant()), prev);
 473             assertEquals(test.previousTransition(prev.getInstant().plusSeconds(1)), prev);
 474             assertEquals(test.previousTransition(prev.getInstant().plusNanos(1)), prev);
 475         }
 476     }
 477 
 478     public void test_London_previousTransition_rulesBased() {
 479         ZoneRules test = europeLondon();
 480         List<ZoneOffsetTransitionRule> rules = test.getTransitionRules();
 481         List<ZoneOffsetTransition> trans = test.getTransitions();
 482 
 483         ZoneOffsetTransition last = trans.get(trans.size() - 1);
 484         assertEquals(test.previousTransition(last.getInstant().plusSeconds(1)), last);
 485         assertEquals(test.previousTransition(last.getInstant().plusNanos(1)), last);
 486 
 487         // Jan 1st of year between transitions and rules
 488         ZonedDateTime odt = ZonedDateTime.ofInstant(last.getInstant(), last.getOffsetAfter());
 489         odt = odt.withDayOfYear(1).plusYears(1).with(LocalTime.MIDNIGHT);
 490         assertEquals(test.previousTransition(odt.toInstant()), last);
 491 
 492         // later years
 493         for (int year = 1998; year < 2010; year++) {
 494             ZoneOffsetTransition a = rules.get(0).createTransition(year);
 495             ZoneOffsetTransition b = rules.get(1).createTransition(year);
 496             ZoneOffsetTransition c = rules.get(0).createTransition(year + 1);
 497 
 498             assertEquals(test.previousTransition(c.getInstant()), b);
 499             assertEquals(test.previousTransition(b.getInstant().plusSeconds(1)), b);
 500             assertEquals(test.previousTransition(b.getInstant().plusNanos(1)), b);
 501 
 502             assertEquals(test.previousTransition(b.getInstant()), a);
 503             assertEquals(test.previousTransition(a.getInstant().plusSeconds(1)), a);
 504             assertEquals(test.previousTransition(a.getInstant().plusNanos(1)), a);
 505         }
 506     }
 507 
 508     //-----------------------------------------------------------------------
 509     // Europe/Paris
 510     //-----------------------------------------------------------------------
 511     private ZoneRules europeParis() {
 512         return ZoneId.of("Europe/Paris").getRules();
 513     }
 514 
 515     public void test_Paris() {
 516         ZoneRules test = europeParis();
 517         assertEquals(test.isFixedOffset(), false);
 518     }
 519 
 520     public void test_Paris_preTimeZones() {
 521         ZoneRules test = europeParis();
 522         ZonedDateTime old = createZDT(1800, 1, 1, ZoneOffset.UTC);
 523         Instant instant = old.toInstant();
 524         ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(0, 9, 21);
 525         assertEquals(test.getOffset(instant), offset);
 526         checkOffset(test, old.toLocalDateTime(), offset, 1);
 527         assertEquals(test.getStandardOffset(instant), offset);
 528         assertEquals(test.getDaylightSavings(instant), Duration.ZERO);
 529         assertEquals(test.isDaylightSavings(instant), false);
 530     }
 531 
 532     public void test_Paris_getOffset() {
 533         ZoneRules test = europeParis();
 534         assertEquals(test.getOffset(createInstant(2008, 1, 1, ZoneOffset.UTC)), OFFSET_PONE);
 535         assertEquals(test.getOffset(createInstant(2008, 2, 1, ZoneOffset.UTC)), OFFSET_PONE);
 536         assertEquals(test.getOffset(createInstant(2008, 3, 1, ZoneOffset.UTC)), OFFSET_PONE);
 537         assertEquals(test.getOffset(createInstant(2008, 4, 1, ZoneOffset.UTC)), OFFSET_PTWO);
 538         assertEquals(test.getOffset(createInstant(2008, 5, 1, ZoneOffset.UTC)), OFFSET_PTWO);
 539         assertEquals(test.getOffset(createInstant(2008, 6, 1, ZoneOffset.UTC)), OFFSET_PTWO);
 540         assertEquals(test.getOffset(createInstant(2008, 7, 1, ZoneOffset.UTC)), OFFSET_PTWO);
 541         assertEquals(test.getOffset(createInstant(2008, 8, 1, ZoneOffset.UTC)), OFFSET_PTWO);
 542         assertEquals(test.getOffset(createInstant(2008, 9, 1, ZoneOffset.UTC)), OFFSET_PTWO);
 543         assertEquals(test.getOffset(createInstant(2008, 10, 1, ZoneOffset.UTC)), OFFSET_PTWO);
 544         assertEquals(test.getOffset(createInstant(2008, 11, 1, ZoneOffset.UTC)), OFFSET_PONE);
 545         assertEquals(test.getOffset(createInstant(2008, 12, 1, ZoneOffset.UTC)), OFFSET_PONE);
 546     }
 547 
 548     public void test_Paris_getOffset_toDST() {
 549         ZoneRules test = europeParis();
 550         assertEquals(test.getOffset(createInstant(2008, 3, 24, ZoneOffset.UTC)), OFFSET_PONE);
 551         assertEquals(test.getOffset(createInstant(2008, 3, 25, ZoneOffset.UTC)), OFFSET_PONE);
 552         assertEquals(test.getOffset(createInstant(2008, 3, 26, ZoneOffset.UTC)), OFFSET_PONE);
 553         assertEquals(test.getOffset(createInstant(2008, 3, 27, ZoneOffset.UTC)), OFFSET_PONE);
 554         assertEquals(test.getOffset(createInstant(2008, 3, 28, ZoneOffset.UTC)), OFFSET_PONE);
 555         assertEquals(test.getOffset(createInstant(2008, 3, 29, ZoneOffset.UTC)), OFFSET_PONE);
 556         assertEquals(test.getOffset(createInstant(2008, 3, 30, ZoneOffset.UTC)), OFFSET_PONE);
 557         assertEquals(test.getOffset(createInstant(2008, 3, 31, ZoneOffset.UTC)), OFFSET_PTWO);
 558         // cutover at 01:00Z
 559         assertEquals(test.getOffset(createInstant(2008, 3, 30, 0, 59, 59, 999999999, ZoneOffset.UTC)), OFFSET_PONE);
 560         assertEquals(test.getOffset(createInstant(2008, 3, 30, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_PTWO);
 561     }
 562 
 563     public void test_Paris_getOffset_fromDST() {
 564         ZoneRules test = europeParis();
 565         assertEquals(test.getOffset(createInstant(2008, 10, 24, ZoneOffset.UTC)), OFFSET_PTWO);
 566         assertEquals(test.getOffset(createInstant(2008, 10, 25, ZoneOffset.UTC)), OFFSET_PTWO);
 567         assertEquals(test.getOffset(createInstant(2008, 10, 26, ZoneOffset.UTC)), OFFSET_PTWO);
 568         assertEquals(test.getOffset(createInstant(2008, 10, 27, ZoneOffset.UTC)), OFFSET_PONE);
 569         assertEquals(test.getOffset(createInstant(2008, 10, 28, ZoneOffset.UTC)), OFFSET_PONE);
 570         assertEquals(test.getOffset(createInstant(2008, 10, 29, ZoneOffset.UTC)), OFFSET_PONE);
 571         assertEquals(test.getOffset(createInstant(2008, 10, 30, ZoneOffset.UTC)), OFFSET_PONE);
 572         assertEquals(test.getOffset(createInstant(2008, 10, 31, ZoneOffset.UTC)), OFFSET_PONE);
 573         // cutover at 01:00Z
 574         assertEquals(test.getOffset(createInstant(2008, 10, 26, 0, 59, 59, 999999999, ZoneOffset.UTC)), OFFSET_PTWO);
 575         assertEquals(test.getOffset(createInstant(2008, 10, 26, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_PONE);
 576     }
 577 
 578     public void test_Paris_getOffsetInfo() {
 579         ZoneRules test = europeParis();
 580         checkOffset(test, createLDT(2008, 1, 1), OFFSET_PONE, 1);
 581         checkOffset(test, createLDT(2008, 2, 1), OFFSET_PONE, 1);
 582         checkOffset(test, createLDT(2008, 3, 1), OFFSET_PONE, 1);
 583         checkOffset(test, createLDT(2008, 4, 1), OFFSET_PTWO, 1);
 584         checkOffset(test, createLDT(2008, 5, 1), OFFSET_PTWO, 1);
 585         checkOffset(test, createLDT(2008, 6, 1), OFFSET_PTWO, 1);
 586         checkOffset(test, createLDT(2008, 7, 1), OFFSET_PTWO, 1);
 587         checkOffset(test, createLDT(2008, 8, 1), OFFSET_PTWO, 1);
 588         checkOffset(test, createLDT(2008, 9, 1), OFFSET_PTWO, 1);
 589         checkOffset(test, createLDT(2008, 10, 1), OFFSET_PTWO, 1);
 590         checkOffset(test, createLDT(2008, 11, 1), OFFSET_PONE, 1);
 591         checkOffset(test, createLDT(2008, 12, 1), OFFSET_PONE, 1);
 592     }
 593 
 594     public void test_Paris_getOffsetInfo_toDST() {
 595         ZoneRules test = europeParis();
 596         checkOffset(test, createLDT(2008, 3, 24), OFFSET_PONE, 1);
 597         checkOffset(test, createLDT(2008, 3, 25), OFFSET_PONE, 1);
 598         checkOffset(test, createLDT(2008, 3, 26), OFFSET_PONE, 1);
 599         checkOffset(test, createLDT(2008, 3, 27), OFFSET_PONE, 1);
 600         checkOffset(test, createLDT(2008, 3, 28), OFFSET_PONE, 1);
 601         checkOffset(test, createLDT(2008, 3, 29), OFFSET_PONE, 1);
 602         checkOffset(test, createLDT(2008, 3, 30), OFFSET_PONE, 1);
 603         checkOffset(test, createLDT(2008, 3, 31), OFFSET_PTWO, 1);
 604         // cutover at 01:00Z which is 02:00+01:00(local Paris time)
 605         checkOffset(test, LocalDateTime.of(2008, 3, 30, 1, 59, 59, 999999999), OFFSET_PONE, 1);
 606         checkOffset(test, LocalDateTime.of(2008, 3, 30, 3, 0, 0, 0), OFFSET_PTWO, 1);
 607     }
 608 
 609     public void test_Paris_getOffsetInfo_fromDST() {
 610         ZoneRules test = europeParis();
 611         checkOffset(test, createLDT(2008, 10, 24), OFFSET_PTWO, 1);
 612         checkOffset(test, createLDT(2008, 10, 25), OFFSET_PTWO, 1);
 613         checkOffset(test, createLDT(2008, 10, 26), OFFSET_PTWO, 1);
 614         checkOffset(test, createLDT(2008, 10, 27), OFFSET_PONE, 1);
 615         checkOffset(test, createLDT(2008, 10, 28), OFFSET_PONE, 1);
 616         checkOffset(test, createLDT(2008, 10, 29), OFFSET_PONE, 1);
 617         checkOffset(test, createLDT(2008, 10, 30), OFFSET_PONE, 1);
 618         checkOffset(test, createLDT(2008, 10, 31), OFFSET_PONE, 1);
 619         // cutover at 01:00Z which is 02:00+01:00(local Paris time)
 620         checkOffset(test, LocalDateTime.of(2008, 10, 26, 1, 59, 59, 999999999), OFFSET_PTWO, 1);
 621         checkOffset(test, LocalDateTime.of(2008, 10, 26, 3, 0, 0, 0), OFFSET_PONE, 1);
 622     }
 623 
 624     public void test_Paris_getOffsetInfo_gap() {
 625         ZoneRules test = europeParis();
 626         final LocalDateTime dateTime = LocalDateTime.of(2008, 3, 30, 2, 0, 0, 0);
 627         ZoneOffsetTransition trans = checkOffset(test, dateTime, OFFSET_PONE, GAP);
 628         assertEquals(trans.isGap(), true);
 629         assertEquals(trans.isOverlap(), false);
 630         assertEquals(trans.getOffsetBefore(), OFFSET_PONE);
 631         assertEquals(trans.getOffsetAfter(), OFFSET_PTWO);
 632         assertEquals(trans.getInstant(), createInstant(2008, 3, 30, 1, 0, ZoneOffset.UTC));
 633         assertEquals(trans.isValidOffset(OFFSET_ZERO), false);
 634         assertEquals(trans.isValidOffset(OFFSET_PONE), false);
 635         assertEquals(trans.isValidOffset(OFFSET_PTWO), false);
 636         assertEquals(trans.toString(), "Transition[Gap at 2008-03-30T02:00+01:00 to +02:00]");
 637 
 638         assertFalse(trans.equals(null));
 639         assertFalse(trans.equals(OFFSET_PONE));
 640         assertTrue(trans.equals(trans));
 641 
 642         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
 643         assertTrue(trans.equals(otherTrans));
 644         assertEquals(trans.hashCode(), otherTrans.hashCode());
 645     }
 646 
 647     public void test_Paris_getOffsetInfo_overlap() {
 648         ZoneRules test = europeParis();
 649         final LocalDateTime dateTime = LocalDateTime.of(2008, 10, 26, 2, 0, 0, 0);
 650         ZoneOffsetTransition trans = checkOffset(test, dateTime, OFFSET_PTWO, OVERLAP);
 651         assertEquals(trans.isGap(), false);
 652         assertEquals(trans.isOverlap(), true);
 653         assertEquals(trans.getOffsetBefore(), OFFSET_PTWO);
 654         assertEquals(trans.getOffsetAfter(), OFFSET_PONE);
 655         assertEquals(trans.getInstant(), createInstant(2008, 10, 26, 1, 0, ZoneOffset.UTC));
 656         assertEquals(trans.isValidOffset(OFFSET_ZERO), false);
 657         assertEquals(trans.isValidOffset(OFFSET_PONE), true);
 658         assertEquals(trans.isValidOffset(OFFSET_PTWO), true);
 659         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(3)), false);
 660         assertEquals(trans.toString(), "Transition[Overlap at 2008-10-26T03:00+02:00 to +01:00]");
 661 
 662         assertFalse(trans.equals(null));
 663         assertFalse(trans.equals(OFFSET_PTWO));
 664         assertTrue(trans.equals(trans));
 665 
 666         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
 667         assertTrue(trans.equals(otherTrans));
 668         assertEquals(trans.hashCode(), otherTrans.hashCode());
 669     }
 670 
 671     public void test_Paris_getStandardOffset() {
 672         ZoneRules test = europeParis();
 673         ZonedDateTime zdt = createZDT(1840, 1, 1, ZoneOffset.UTC);
 674         while (zdt.getYear() < 2010) {
 675             Instant instant = zdt.toInstant();
 676             if (zdt.toLocalDate().isBefore(LocalDate.of(1911, 3, 11))) {
 677                 assertEquals(test.getStandardOffset(instant), ZoneOffset.ofHoursMinutesSeconds(0, 9, 21));
 678             } else if (zdt.toLocalDate().isBefore(LocalDate.of(1940, 6, 14))) {
 679                 assertEquals(test.getStandardOffset(instant), OFFSET_ZERO);
 680             } else if (zdt.toLocalDate().isBefore(LocalDate.of(1944, 8, 25))) {
 681                 assertEquals(test.getStandardOffset(instant), OFFSET_PONE);
 682             } else if (zdt.toLocalDate().isBefore(LocalDate.of(1945, 9, 16))) {
 683                 assertEquals(test.getStandardOffset(instant), OFFSET_ZERO);
 684             } else {
 685                 assertEquals(test.getStandardOffset(instant), OFFSET_PONE);
 686             }
 687             zdt = zdt.plusMonths(6);
 688         }
 689     }
 690 
 691     //-----------------------------------------------------------------------
 692     // America/New_York
 693     //-----------------------------------------------------------------------
 694     private ZoneRules americaNewYork() {
 695         return ZoneId.of("America/New_York").getRules();
 696     }
 697 
 698     public void test_NewYork() {
 699         ZoneRules test = americaNewYork();
 700         assertEquals(test.isFixedOffset(), false);
 701     }
 702 
 703     public void test_NewYork_preTimeZones() {
 704         ZoneRules test = americaNewYork();
 705         ZonedDateTime old = createZDT(1800, 1, 1, ZoneOffset.UTC);
 706         Instant instant = old.toInstant();
 707         ZoneOffset offset = ZoneOffset.of("-04:56:02");
 708         assertEquals(test.getOffset(instant), offset);
 709         checkOffset(test, old.toLocalDateTime(), offset, 1);
 710         assertEquals(test.getStandardOffset(instant), offset);
 711         assertEquals(test.getDaylightSavings(instant), Duration.ZERO);
 712         assertEquals(test.isDaylightSavings(instant), false);
 713     }
 714 
 715     public void test_NewYork_getOffset() {
 716         ZoneRules test = americaNewYork();
 717         ZoneOffset offset = ZoneOffset.ofHours(-5);
 718         assertEquals(test.getOffset(createInstant(2008, 1, 1, offset)), ZoneOffset.ofHours(-5));
 719         assertEquals(test.getOffset(createInstant(2008, 2, 1, offset)), ZoneOffset.ofHours(-5));
 720         assertEquals(test.getOffset(createInstant(2008, 3, 1, offset)), ZoneOffset.ofHours(-5));
 721         assertEquals(test.getOffset(createInstant(2008, 4, 1, offset)), ZoneOffset.ofHours(-4));
 722         assertEquals(test.getOffset(createInstant(2008, 5, 1, offset)), ZoneOffset.ofHours(-4));
 723         assertEquals(test.getOffset(createInstant(2008, 6, 1, offset)), ZoneOffset.ofHours(-4));
 724         assertEquals(test.getOffset(createInstant(2008, 7, 1, offset)), ZoneOffset.ofHours(-4));
 725         assertEquals(test.getOffset(createInstant(2008, 8, 1, offset)), ZoneOffset.ofHours(-4));
 726         assertEquals(test.getOffset(createInstant(2008, 9, 1, offset)), ZoneOffset.ofHours(-4));
 727         assertEquals(test.getOffset(createInstant(2008, 10, 1, offset)), ZoneOffset.ofHours(-4));
 728         assertEquals(test.getOffset(createInstant(2008, 11, 1, offset)), ZoneOffset.ofHours(-4));
 729         assertEquals(test.getOffset(createInstant(2008, 12, 1, offset)), ZoneOffset.ofHours(-5));
 730         assertEquals(test.getOffset(createInstant(2008, 1, 28, offset)), ZoneOffset.ofHours(-5));
 731         assertEquals(test.getOffset(createInstant(2008, 2, 28, offset)), ZoneOffset.ofHours(-5));
 732         assertEquals(test.getOffset(createInstant(2008, 3, 28, offset)), ZoneOffset.ofHours(-4));
 733         assertEquals(test.getOffset(createInstant(2008, 4, 28, offset)), ZoneOffset.ofHours(-4));
 734         assertEquals(test.getOffset(createInstant(2008, 5, 28, offset)), ZoneOffset.ofHours(-4));
 735         assertEquals(test.getOffset(createInstant(2008, 6, 28, offset)), ZoneOffset.ofHours(-4));
 736         assertEquals(test.getOffset(createInstant(2008, 7, 28, offset)), ZoneOffset.ofHours(-4));
 737         assertEquals(test.getOffset(createInstant(2008, 8, 28, offset)), ZoneOffset.ofHours(-4));
 738         assertEquals(test.getOffset(createInstant(2008, 9, 28, offset)), ZoneOffset.ofHours(-4));
 739         assertEquals(test.getOffset(createInstant(2008, 10, 28, offset)), ZoneOffset.ofHours(-4));
 740         assertEquals(test.getOffset(createInstant(2008, 11, 28, offset)), ZoneOffset.ofHours(-5));
 741         assertEquals(test.getOffset(createInstant(2008, 12, 28, offset)), ZoneOffset.ofHours(-5));
 742     }
 743 
 744     public void test_NewYork_getOffset_toDST() {
 745         ZoneRules test = americaNewYork();
 746         ZoneOffset offset = ZoneOffset.ofHours(-5);
 747         assertEquals(test.getOffset(createInstant(2008, 3, 8, offset)), ZoneOffset.ofHours(-5));
 748         assertEquals(test.getOffset(createInstant(2008, 3, 9, offset)), ZoneOffset.ofHours(-5));
 749         assertEquals(test.getOffset(createInstant(2008, 3, 10, offset)), ZoneOffset.ofHours(-4));
 750         assertEquals(test.getOffset(createInstant(2008, 3, 11, offset)), ZoneOffset.ofHours(-4));
 751         assertEquals(test.getOffset(createInstant(2008, 3, 12, offset)), ZoneOffset.ofHours(-4));
 752         assertEquals(test.getOffset(createInstant(2008, 3, 13, offset)), ZoneOffset.ofHours(-4));
 753         assertEquals(test.getOffset(createInstant(2008, 3, 14, offset)), ZoneOffset.ofHours(-4));
 754         // cutover at 02:00 local
 755         assertEquals(test.getOffset(createInstant(2008, 3, 9, 1, 59, 59, 999999999, offset)), ZoneOffset.ofHours(-5));
 756         assertEquals(test.getOffset(createInstant(2008, 3, 9, 2, 0, 0, 0, offset)), ZoneOffset.ofHours(-4));
 757     }
 758 
 759     public void test_NewYork_getOffset_fromDST() {
 760         ZoneRules test = americaNewYork();
 761         ZoneOffset offset = ZoneOffset.ofHours(-4);
 762         assertEquals(test.getOffset(createInstant(2008, 11, 1, offset)), ZoneOffset.ofHours(-4));
 763         assertEquals(test.getOffset(createInstant(2008, 11, 2, offset)), ZoneOffset.ofHours(-4));
 764         assertEquals(test.getOffset(createInstant(2008, 11, 3, offset)), ZoneOffset.ofHours(-5));
 765         assertEquals(test.getOffset(createInstant(2008, 11, 4, offset)), ZoneOffset.ofHours(-5));
 766         assertEquals(test.getOffset(createInstant(2008, 11, 5, offset)), ZoneOffset.ofHours(-5));
 767         assertEquals(test.getOffset(createInstant(2008, 11, 6, offset)), ZoneOffset.ofHours(-5));
 768         assertEquals(test.getOffset(createInstant(2008, 11, 7, offset)), ZoneOffset.ofHours(-5));
 769         // cutover at 02:00 local
 770         assertEquals(test.getOffset(createInstant(2008, 11, 2, 1, 59, 59, 999999999, offset)), ZoneOffset.ofHours(-4));
 771         assertEquals(test.getOffset(createInstant(2008, 11, 2, 2, 0, 0, 0, offset)), ZoneOffset.ofHours(-5));
 772     }
 773 
 774     public void test_NewYork_getOffsetInfo() {
 775         ZoneRules test = americaNewYork();
 776         checkOffset(test, createLDT(2008, 1, 1), ZoneOffset.ofHours(-5), 1);
 777         checkOffset(test, createLDT(2008, 2, 1), ZoneOffset.ofHours(-5), 1);
 778         checkOffset(test, createLDT(2008, 3, 1), ZoneOffset.ofHours(-5), 1);
 779         checkOffset(test, createLDT(2008, 4, 1), ZoneOffset.ofHours(-4), 1);
 780         checkOffset(test, createLDT(2008, 5, 1), ZoneOffset.ofHours(-4), 1);
 781         checkOffset(test, createLDT(2008, 6, 1), ZoneOffset.ofHours(-4), 1);
 782         checkOffset(test, createLDT(2008, 7, 1), ZoneOffset.ofHours(-4), 1);
 783         checkOffset(test, createLDT(2008, 8, 1), ZoneOffset.ofHours(-4), 1);
 784         checkOffset(test, createLDT(2008, 9, 1), ZoneOffset.ofHours(-4), 1);
 785         checkOffset(test, createLDT(2008, 10, 1), ZoneOffset.ofHours(-4), 1);
 786         checkOffset(test, createLDT(2008, 11, 1), ZoneOffset.ofHours(-4), 1);
 787         checkOffset(test, createLDT(2008, 12, 1), ZoneOffset.ofHours(-5), 1);
 788         checkOffset(test, createLDT(2008, 1, 28), ZoneOffset.ofHours(-5), 1);
 789         checkOffset(test, createLDT(2008, 2, 28), ZoneOffset.ofHours(-5), 1);
 790         checkOffset(test, createLDT(2008, 3, 28), ZoneOffset.ofHours(-4), 1);
 791         checkOffset(test, createLDT(2008, 4, 28), ZoneOffset.ofHours(-4), 1);
 792         checkOffset(test, createLDT(2008, 5, 28), ZoneOffset.ofHours(-4), 1);
 793         checkOffset(test, createLDT(2008, 6, 28), ZoneOffset.ofHours(-4), 1);
 794         checkOffset(test, createLDT(2008, 7, 28), ZoneOffset.ofHours(-4), 1);
 795         checkOffset(test, createLDT(2008, 8, 28), ZoneOffset.ofHours(-4), 1);
 796         checkOffset(test, createLDT(2008, 9, 28), ZoneOffset.ofHours(-4), 1);
 797         checkOffset(test, createLDT(2008, 10, 28), ZoneOffset.ofHours(-4), 1);
 798         checkOffset(test, createLDT(2008, 11, 28), ZoneOffset.ofHours(-5), 1);
 799         checkOffset(test, createLDT(2008, 12, 28), ZoneOffset.ofHours(-5), 1);
 800     }
 801 
 802     public void test_NewYork_getOffsetInfo_toDST() {
 803         ZoneRules test = americaNewYork();
 804         checkOffset(test, createLDT(2008, 3, 8), ZoneOffset.ofHours(-5), 1);
 805         checkOffset(test, createLDT(2008, 3, 9), ZoneOffset.ofHours(-5), 1);
 806         checkOffset(test, createLDT(2008, 3, 10), ZoneOffset.ofHours(-4), 1);
 807         checkOffset(test, createLDT(2008, 3, 11), ZoneOffset.ofHours(-4), 1);
 808         checkOffset(test, createLDT(2008, 3, 12), ZoneOffset.ofHours(-4), 1);
 809         checkOffset(test, createLDT(2008, 3, 13), ZoneOffset.ofHours(-4), 1);
 810         checkOffset(test, createLDT(2008, 3, 14), ZoneOffset.ofHours(-4), 1);
 811         // cutover at 02:00 local
 812         checkOffset(test, LocalDateTime.of(2008, 3, 9, 1, 59, 59, 999999999), ZoneOffset.ofHours(-5), 1);
 813         checkOffset(test, LocalDateTime.of(2008, 3, 9, 3, 0, 0, 0), ZoneOffset.ofHours(-4), 1);
 814     }
 815 
 816     public void test_NewYork_getOffsetInfo_fromDST() {
 817         ZoneRules test = americaNewYork();
 818         checkOffset(test, createLDT(2008, 11, 1), ZoneOffset.ofHours(-4), 1);
 819         checkOffset(test, createLDT(2008, 11, 2), ZoneOffset.ofHours(-4), 1);
 820         checkOffset(test, createLDT(2008, 11, 3), ZoneOffset.ofHours(-5), 1);
 821         checkOffset(test, createLDT(2008, 11, 4), ZoneOffset.ofHours(-5), 1);
 822         checkOffset(test, createLDT(2008, 11, 5), ZoneOffset.ofHours(-5), 1);
 823         checkOffset(test, createLDT(2008, 11, 6), ZoneOffset.ofHours(-5), 1);
 824         checkOffset(test, createLDT(2008, 11, 7), ZoneOffset.ofHours(-5), 1);
 825         // cutover at 02:00 local
 826         checkOffset(test, LocalDateTime.of(2008, 11, 2, 0, 59, 59, 999999999), ZoneOffset.ofHours(-4), 1);
 827         checkOffset(test, LocalDateTime.of(2008, 11, 2, 2, 0, 0, 0), ZoneOffset.ofHours(-5), 1);
 828     }
 829 
 830     public void test_NewYork_getOffsetInfo_gap() {
 831         ZoneRules test = americaNewYork();
 832         final LocalDateTime dateTime = LocalDateTime.of(2008, 3, 9, 2, 0, 0, 0);
 833         ZoneOffsetTransition trans = checkOffset(test, dateTime, ZoneOffset.ofHours(-5), GAP);
 834         assertEquals(trans.isGap(), true);
 835         assertEquals(trans.isOverlap(), false);
 836         assertEquals(trans.getOffsetBefore(), ZoneOffset.ofHours(-5));
 837         assertEquals(trans.getOffsetAfter(), ZoneOffset.ofHours(-4));
 838         assertEquals(trans.getInstant(), createInstant(2008, 3, 9, 2, 0, ZoneOffset.ofHours(-5)));
 839         assertEquals(trans.isValidOffset(OFFSET_PTWO), false);
 840         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-5)), false);
 841         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-4)), false);
 842         assertEquals(trans.toString(), "Transition[Gap at 2008-03-09T02:00-05:00 to -04:00]");
 843 
 844         assertFalse(trans.equals(null));
 845         assertFalse(trans.equals(ZoneOffset.ofHours(-5)));
 846         assertTrue(trans.equals(trans));
 847 
 848         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
 849         assertTrue(trans.equals(otherTrans));
 850         assertEquals(trans.hashCode(), otherTrans.hashCode());
 851     }
 852 
 853     public void test_NewYork_getOffsetInfo_overlap() {
 854         ZoneRules test = americaNewYork();
 855         final LocalDateTime dateTime = LocalDateTime.of(2008, 11, 2, 1, 0, 0, 0);
 856         ZoneOffsetTransition trans = checkOffset(test, dateTime, ZoneOffset.ofHours(-4), OVERLAP);
 857         assertEquals(trans.isGap(), false);
 858         assertEquals(trans.isOverlap(), true);
 859         assertEquals(trans.getOffsetBefore(), ZoneOffset.ofHours(-4));
 860         assertEquals(trans.getOffsetAfter(), ZoneOffset.ofHours(-5));
 861         assertEquals(trans.getInstant(), createInstant(2008, 11, 2, 2, 0, ZoneOffset.ofHours(-4)));
 862         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-1)), false);
 863         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-5)), true);
 864         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-4)), true);
 865         assertEquals(trans.isValidOffset(OFFSET_PTWO), false);
 866         assertEquals(trans.toString(), "Transition[Overlap at 2008-11-02T02:00-04:00 to -05:00]");
 867 
 868         assertFalse(trans.equals(null));
 869         assertFalse(trans.equals(ZoneOffset.ofHours(-4)));
 870         assertTrue(trans.equals(trans));
 871 
 872         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
 873         assertTrue(trans.equals(otherTrans));
 874         assertEquals(trans.hashCode(), otherTrans.hashCode());
 875     }
 876 
 877     public void test_NewYork_getStandardOffset() {
 878         ZoneRules test = americaNewYork();
 879         ZonedDateTime dateTime = createZDT(1860, 1, 1, ZoneOffset.UTC);
 880         while (dateTime.getYear() < 2010) {
 881             Instant instant = dateTime.toInstant();
 882             if (dateTime.toLocalDate().isBefore(LocalDate.of(1883, 11, 18))) {
 883                 assertEquals(test.getStandardOffset(instant), ZoneOffset.of("-04:56:02"));
 884             } else {
 885                 assertEquals(test.getStandardOffset(instant), ZoneOffset.ofHours(-5));
 886             }
 887             dateTime = dateTime.plusMonths(6);
 888         }
 889     }
 890 
 891     //-----------------------------------------------------------------------
 892     // Kathmandu
 893     //-----------------------------------------------------------------------
 894     private ZoneRules asiaKathmandu() {
 895         return ZoneId.of("Asia/Kathmandu").getRules();
 896     }
 897 
 898     public void test_Kathmandu_nextTransition_historic() {
 899         ZoneRules test = asiaKathmandu();
 900         List<ZoneOffsetTransition> trans = test.getTransitions();
 901 
 902         ZoneOffsetTransition first = trans.get(0);
 903         assertEquals(test.nextTransition(first.getInstant().minusNanos(1)), first);
 904 
 905         for (int i = 0; i < trans.size() - 1; i++) {
 906             ZoneOffsetTransition cur = trans.get(i);
 907             ZoneOffsetTransition next = trans.get(i + 1);
 908 
 909             assertEquals(test.nextTransition(cur.getInstant()), next);
 910             assertEquals(test.nextTransition(next.getInstant().minusNanos(1)), next);
 911         }
 912     }
 913 
 914     public void test_Kathmandu_nextTransition_noRules() {
 915         ZoneRules test = asiaKathmandu();
 916         List<ZoneOffsetTransition> trans = test.getTransitions();
 917 
 918         ZoneOffsetTransition last = trans.get(trans.size() - 1);
 919         assertEquals(test.nextTransition(last.getInstant()), null);
 920     }
 921 
 922     //-------------------------------------------------------------------------
 923     @Test(expectedExceptions=UnsupportedOperationException.class)
 924     public void test_getTransitions_immutable() {
 925         ZoneRules test = europeParis();
 926         test.getTransitions().clear();
 927     }
 928 
 929     @Test(expectedExceptions=UnsupportedOperationException.class)
 930     public void test_getTransitionRules_immutable() {
 931         ZoneRules test = europeParis();
 932         test.getTransitionRules().clear();
 933     }
 934 
 935     //-----------------------------------------------------------------------
 936     // equals() / hashCode()
 937     //-----------------------------------------------------------------------
 938     public void test_equals() {
 939         ZoneRules test1 = europeLondon();
 940         ZoneRules test2 = europeParis();
 941         ZoneRules test2b = europeParis();
 942         assertEquals(test1.equals(test2), false);
 943         assertEquals(test2.equals(test1), false);
 944 
 945         assertEquals(test1.equals(test1), true);
 946         assertEquals(test2.equals(test2), true);
 947         assertEquals(test2.equals(test2b), true);
 948 
 949         assertEquals(test1.hashCode() == test1.hashCode(), true);
 950         assertEquals(test2.hashCode() == test2.hashCode(), true);
 951         assertEquals(test2.hashCode() == test2b.hashCode(), true);
 952     }
 953 
 954     public void test_equals_null() {
 955         assertEquals(europeLondon().equals(null), false);
 956     }
 957 
 958     public void test_equals_notZoneRules() {
 959         assertEquals(europeLondon().equals("Europe/London"), false);
 960     }
 961 
 962     public void test_toString() {
 963         assertEquals(europeLondon().toString().contains("ZoneRules"), true);
 964     }
 965 
 966     //-----------------------------------------------------------------------
 967     //-----------------------------------------------------------------------
 968     //-----------------------------------------------------------------------
 969     private Instant createInstant(int year, int month, int day, ZoneOffset offset) {
 970         return LocalDateTime.of(year, month, day, 0, 0).toInstant(offset);
 971     }
 972 
 973     private Instant createInstant(int year, int month, int day, int hour, int min, ZoneOffset offset) {
 974         return LocalDateTime.of(year, month, day, hour, min).toInstant(offset);
 975     }
 976 
 977     private Instant createInstant(int year, int month, int day, int hour, int min, int sec, int nano, ZoneOffset offset) {
 978         return LocalDateTime.of(year, month, day, hour, min, sec, nano).toInstant(offset);
 979     }
 980 
 981     private ZonedDateTime createZDT(int year, int month, int day, ZoneId zone) {
 982         return LocalDateTime.of(year, month, day, 0, 0).atZone(zone);
 983     }
 984 
 985     private LocalDateTime createLDT(int year, int month, int day) {
 986         return LocalDateTime.of(year, month, day, 0, 0);
 987     }
 988 
 989     private ZoneOffsetTransition checkOffset(ZoneRules rules, LocalDateTime dateTime, ZoneOffset offset, int type) {
 990         List<ZoneOffset> validOffsets = rules.getValidOffsets(dateTime);
 991         assertEquals(validOffsets.size(), type);
 992         assertEquals(rules.getOffset(dateTime), offset);
 993         if (type == 1) {
 994             assertEquals(validOffsets.get(0), offset);
 995             return null;
 996         } else {
 997             ZoneOffsetTransition zot = rules.getTransition(dateTime);
 998             assertNotNull(zot);
 999             assertEquals(zot.isOverlap(), type == 2);
1000             assertEquals(zot.isGap(), type == 0);
1001             assertEquals(zot.isValidOffset(offset), type == 2);
1002             return zot;
1003         }
1004     }
1005 
1006 }