1 /*
2  * Copyright (c) 2012, 2018, 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.time.DayOfWeek;
72 import java.time.Duration;
73 import java.time.Instant;
74 import java.time.LocalDate;
75 import java.time.LocalDateTime;
76 import java.time.LocalTime;
77 import java.time.Month;
78 import java.time.OffsetDateTime;
79 import java.time.Year;
80 import java.time.ZoneId;
81 import java.time.ZoneOffset;
82 import java.time.ZonedDateTime;
83 import java.time.zone.ZoneOffsetTransition;
84 import java.time.zone.ZoneOffsetTransitionRule;
85 import java.time.zone.ZoneOffsetTransitionRule.TimeDefinition;
86 import java.time.zone.ZoneRules;
87 import java.util.ArrayList;
88 import java.util.Iterator;
89 import java.util.List;
90 
91 import org.testng.annotations.Test;
92 
93 /**
94  * Test ZoneRules.
95  */
96 @Test
97 public class TCKZoneRules {
98 
99     private static final ZoneOffset OFFSET_ZERO = ZoneOffset.ofHours(0);
100     private static final ZoneOffset OFFSET_PONE = ZoneOffset.ofHours(1);
101     private static final ZoneOffset OFFSET_PTWO = ZoneOffset.ofHours(2);
102     public static final String LATEST_TZDB = "2009b";
103     private static final int OVERLAP = 2;
104     private static final int GAP = 0;
105 
106 
107 
108     //-----------------------------------------------------------------------
109     // Europe/London
110     //-----------------------------------------------------------------------
europeLondon()111     private ZoneRules europeLondon() {
112         return ZoneId.of("Europe/London").getRules();
113     }
114 
115     @Test
test_London()116     public void test_London() {
117         ZoneRules test = europeLondon();
118         assertEquals(test.isFixedOffset(), false);
119     }
120 
121     @Test
test_London_preTimeZones()122     public void test_London_preTimeZones() {
123         ZoneRules test = europeLondon();
124         ZonedDateTime old = createZDT(1800, 1, 1, ZoneOffset.UTC);
125         Instant instant = old.toInstant();
126         ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(0, -1, -15);
127         assertEquals(test.getOffset(instant), offset);
128         checkOffset(test, old.toLocalDateTime(), offset, 1);
129         assertEquals(test.getStandardOffset(instant), offset);
130         assertEquals(test.getDaylightSavings(instant), Duration.ZERO);
131         assertEquals(test.isDaylightSavings(instant), false);
132     }
133 
134     @Test
test_London_getOffset()135     public void test_London_getOffset() {
136         ZoneRules test = europeLondon();
137         assertEquals(test.getOffset(createInstant(2008, 1, 1, ZoneOffset.UTC)), OFFSET_ZERO);
138         assertEquals(test.getOffset(createInstant(2008, 2, 1, ZoneOffset.UTC)), OFFSET_ZERO);
139         assertEquals(test.getOffset(createInstant(2008, 3, 1, ZoneOffset.UTC)), OFFSET_ZERO);
140         assertEquals(test.getOffset(createInstant(2008, 4, 1, ZoneOffset.UTC)), OFFSET_PONE);
141         assertEquals(test.getOffset(createInstant(2008, 5, 1, ZoneOffset.UTC)), OFFSET_PONE);
142         assertEquals(test.getOffset(createInstant(2008, 6, 1, ZoneOffset.UTC)), OFFSET_PONE);
143         assertEquals(test.getOffset(createInstant(2008, 7, 1, ZoneOffset.UTC)), OFFSET_PONE);
144         assertEquals(test.getOffset(createInstant(2008, 8, 1, ZoneOffset.UTC)), OFFSET_PONE);
145         assertEquals(test.getOffset(createInstant(2008, 9, 1, ZoneOffset.UTC)), OFFSET_PONE);
146         assertEquals(test.getOffset(createInstant(2008, 10, 1, ZoneOffset.UTC)), OFFSET_PONE);
147         assertEquals(test.getOffset(createInstant(2008, 11, 1, ZoneOffset.UTC)), OFFSET_ZERO);
148         assertEquals(test.getOffset(createInstant(2008, 12, 1, ZoneOffset.UTC)), OFFSET_ZERO);
149     }
150 
151     @Test
test_London_getOffset_toDST()152     public void test_London_getOffset_toDST() {
153         ZoneRules test = europeLondon();
154         assertEquals(test.getOffset(createInstant(2008, 3, 24, ZoneOffset.UTC)), OFFSET_ZERO);
155         assertEquals(test.getOffset(createInstant(2008, 3, 25, ZoneOffset.UTC)), OFFSET_ZERO);
156         assertEquals(test.getOffset(createInstant(2008, 3, 26, ZoneOffset.UTC)), OFFSET_ZERO);
157         assertEquals(test.getOffset(createInstant(2008, 3, 27, ZoneOffset.UTC)), OFFSET_ZERO);
158         assertEquals(test.getOffset(createInstant(2008, 3, 28, ZoneOffset.UTC)), OFFSET_ZERO);
159         assertEquals(test.getOffset(createInstant(2008, 3, 29, ZoneOffset.UTC)), OFFSET_ZERO);
160         assertEquals(test.getOffset(createInstant(2008, 3, 30, ZoneOffset.UTC)), OFFSET_ZERO);
161         assertEquals(test.getOffset(createInstant(2008, 3, 31, ZoneOffset.UTC)), OFFSET_PONE);
162         // cutover at 01:00Z
163         assertEquals(test.getOffset(createInstant(2008, 3, 30, 0, 59, 59, 999999999, ZoneOffset.UTC)), OFFSET_ZERO);
164         assertEquals(test.getOffset(createInstant(2008, 3, 30, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_PONE);
165     }
166 
167     @Test
test_London_getOffset_fromDST()168     public void test_London_getOffset_fromDST() {
169         ZoneRules test = europeLondon();
170         assertEquals(test.getOffset(createInstant(2008, 10, 24, ZoneOffset.UTC)), OFFSET_PONE);
171         assertEquals(test.getOffset(createInstant(2008, 10, 25, ZoneOffset.UTC)), OFFSET_PONE);
172         assertEquals(test.getOffset(createInstant(2008, 10, 26, ZoneOffset.UTC)), OFFSET_PONE);
173         assertEquals(test.getOffset(createInstant(2008, 10, 27, ZoneOffset.UTC)), OFFSET_ZERO);
174         assertEquals(test.getOffset(createInstant(2008, 10, 28, ZoneOffset.UTC)), OFFSET_ZERO);
175         assertEquals(test.getOffset(createInstant(2008, 10, 29, ZoneOffset.UTC)), OFFSET_ZERO);
176         assertEquals(test.getOffset(createInstant(2008, 10, 30, ZoneOffset.UTC)), OFFSET_ZERO);
177         assertEquals(test.getOffset(createInstant(2008, 10, 31, ZoneOffset.UTC)), OFFSET_ZERO);
178         // cutover at 01:00Z
179         assertEquals(test.getOffset(createInstant(2008, 10, 26, 0, 59, 59, 999999999, ZoneOffset.UTC)), OFFSET_PONE);
180         assertEquals(test.getOffset(createInstant(2008, 10, 26, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_ZERO);
181     }
182 
183     @Test
test_London_getOffsetInfo()184     public void test_London_getOffsetInfo() {
185         ZoneRules test = europeLondon();
186         checkOffset(test, createLDT(2008, 1, 1), OFFSET_ZERO, 1);
187         checkOffset(test, createLDT(2008, 2, 1), OFFSET_ZERO, 1);
188         checkOffset(test, createLDT(2008, 3, 1), OFFSET_ZERO, 1);
189         checkOffset(test, createLDT(2008, 4, 1), OFFSET_PONE, 1);
190         checkOffset(test, createLDT(2008, 5, 1), OFFSET_PONE, 1);
191         checkOffset(test, createLDT(2008, 6, 1), OFFSET_PONE, 1);
192         checkOffset(test, createLDT(2008, 7, 1), OFFSET_PONE, 1);
193         checkOffset(test, createLDT(2008, 8, 1), OFFSET_PONE, 1);
194         checkOffset(test, createLDT(2008, 9, 1), OFFSET_PONE, 1);
195         checkOffset(test, createLDT(2008, 10, 1), OFFSET_PONE, 1);
196         checkOffset(test, createLDT(2008, 11, 1), OFFSET_ZERO, 1);
197         checkOffset(test, createLDT(2008, 12, 1), OFFSET_ZERO, 1);
198     }
199 
200     @Test
test_London_getOffsetInfo_toDST()201     public void test_London_getOffsetInfo_toDST() {
202         ZoneRules test = europeLondon();
203         checkOffset(test, createLDT(2008, 3, 24), OFFSET_ZERO, 1);
204         checkOffset(test, createLDT(2008, 3, 25), OFFSET_ZERO, 1);
205         checkOffset(test, createLDT(2008, 3, 26), OFFSET_ZERO, 1);
206         checkOffset(test, createLDT(2008, 3, 27), OFFSET_ZERO, 1);
207         checkOffset(test, createLDT(2008, 3, 28), OFFSET_ZERO, 1);
208         checkOffset(test, createLDT(2008, 3, 29), OFFSET_ZERO, 1);
209         checkOffset(test, createLDT(2008, 3, 30), OFFSET_ZERO, 1);
210         checkOffset(test, createLDT(2008, 3, 31), OFFSET_PONE, 1);
211         // cutover at 01:00Z
212         checkOffset(test, LocalDateTime.of(2008, 3, 30, 0, 59, 59, 999999999), OFFSET_ZERO, 1);
213         checkOffset(test, LocalDateTime.of(2008, 3, 30, 2, 0, 0, 0), OFFSET_PONE, 1);
214     }
215 
216     @Test
test_London_getOffsetInfo_fromDST()217     public void test_London_getOffsetInfo_fromDST() {
218         ZoneRules test = europeLondon();
219         checkOffset(test, createLDT(2008, 10, 24), OFFSET_PONE, 1);
220         checkOffset(test, createLDT(2008, 10, 25), OFFSET_PONE, 1);
221         checkOffset(test, createLDT(2008, 10, 26), OFFSET_PONE, 1);
222         checkOffset(test, createLDT(2008, 10, 27), OFFSET_ZERO, 1);
223         checkOffset(test, createLDT(2008, 10, 28), OFFSET_ZERO, 1);
224         checkOffset(test, createLDT(2008, 10, 29), OFFSET_ZERO, 1);
225         checkOffset(test, createLDT(2008, 10, 30), OFFSET_ZERO, 1);
226         checkOffset(test, createLDT(2008, 10, 31), OFFSET_ZERO, 1);
227         // cutover at 01:00Z
228         checkOffset(test, LocalDateTime.of(2008, 10, 26, 0, 59, 59, 999999999), OFFSET_PONE, 1);
229         checkOffset(test, LocalDateTime.of(2008, 10, 26, 2, 0, 0, 0), OFFSET_ZERO, 1);
230     }
231 
232     @Test
test_London_getOffsetInfo_gap()233     public void test_London_getOffsetInfo_gap() {
234         ZoneRules test = europeLondon();
235         final LocalDateTime dateTime = LocalDateTime.of(2008, 3, 30, 1, 0, 0, 0);
236         ZoneOffsetTransition trans = checkOffset(test, dateTime, OFFSET_ZERO, GAP);
237         assertEquals(trans.isGap(), true);
238         assertEquals(trans.isOverlap(), false);
239         assertEquals(trans.getOffsetBefore(), OFFSET_ZERO);
240         assertEquals(trans.getOffsetAfter(), OFFSET_PONE);
241         assertEquals(trans.getInstant(), createInstant(2008, 3, 30, 1, 0, ZoneOffset.UTC));
242         assertEquals(trans.getDateTimeBefore(), LocalDateTime.of(2008, 3, 30, 1, 0));
243         assertEquals(trans.getDateTimeAfter(), LocalDateTime.of(2008, 3, 30, 2, 0));
244         assertEquals(trans.isValidOffset(OFFSET_ZERO), false);
245         assertEquals(trans.isValidOffset(OFFSET_PONE), false);
246         assertEquals(trans.isValidOffset(OFFSET_PTWO), false);
247         assertEquals(trans.toString(), "Transition[Gap at 2008-03-30T01:00Z to +01:00]");
248 
249         assertFalse(trans.equals(null));
250         assertFalse(trans.equals(OFFSET_ZERO));
251         assertTrue(trans.equals(trans));
252 
253         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
254         assertTrue(trans.equals(otherTrans));
255         assertEquals(trans.hashCode(), otherTrans.hashCode());
256     }
257 
258     @Test
test_London_getOffsetInfo_overlap()259     public void test_London_getOffsetInfo_overlap() {
260         ZoneRules test = europeLondon();
261         final LocalDateTime dateTime = LocalDateTime.of(2008, 10, 26, 1, 0, 0, 0);
262         ZoneOffsetTransition trans = checkOffset(test, dateTime, OFFSET_PONE, OVERLAP);
263         assertEquals(trans.isGap(), false);
264         assertEquals(trans.isOverlap(), true);
265         assertEquals(trans.getOffsetBefore(), OFFSET_PONE);
266         assertEquals(trans.getOffsetAfter(), OFFSET_ZERO);
267         assertEquals(trans.getInstant(), createInstant(2008, 10, 26, 1, 0, ZoneOffset.UTC));
268         assertEquals(trans.getDateTimeBefore(), LocalDateTime.of(2008, 10, 26, 2, 0));
269         assertEquals(trans.getDateTimeAfter(), LocalDateTime.of(2008, 10, 26, 1, 0));
270         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-1)), false);
271         assertEquals(trans.isValidOffset(OFFSET_ZERO), true);
272         assertEquals(trans.isValidOffset(OFFSET_PONE), true);
273         assertEquals(trans.isValidOffset(OFFSET_PTWO), false);
274         assertEquals(trans.toString(), "Transition[Overlap at 2008-10-26T02:00+01:00 to Z]");
275 
276         assertFalse(trans.equals(null));
277         assertFalse(trans.equals(OFFSET_PONE));
278         assertTrue(trans.equals(trans));
279 
280         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
281         assertTrue(trans.equals(otherTrans));
282         assertEquals(trans.hashCode(), otherTrans.hashCode());
283     }
284 
285     @Test
test_London_getStandardOffset()286     public void test_London_getStandardOffset() {
287         ZoneRules test = europeLondon();
288         ZonedDateTime zdt = createZDT(1840, 1, 1, ZoneOffset.UTC);
289         while (zdt.getYear() < 2010) {
290             Instant instant = zdt.toInstant();
291             if (zdt.getYear() < 1848) {
292                 assertEquals(test.getStandardOffset(instant), ZoneOffset.ofHoursMinutesSeconds(0, -1, -15));
293             } else if (zdt.getYear() >= 1969 && zdt.getYear() < 1972) {
294                 assertEquals(test.getStandardOffset(instant), OFFSET_PONE);
295             } else {
296                 assertEquals(test.getStandardOffset(instant), OFFSET_ZERO);
297             }
298             zdt = zdt.plusMonths(6);
299         }
300     }
301 
302     @Test
test_London_getTransitions()303     public void test_London_getTransitions() {
304         ZoneRules test = europeLondon();
305         List<ZoneOffsetTransition> trans = test.getTransitions();
306 
307         ZoneOffsetTransition first = trans.get(0);
308         assertEquals(first.getDateTimeBefore(), LocalDateTime.of(1847, 12, 1, 0, 0));
309         assertEquals(first.getOffsetBefore(), ZoneOffset.ofHoursMinutesSeconds(0, -1, -15));
310         assertEquals(first.getOffsetAfter(), OFFSET_ZERO);
311 
312         ZoneOffsetTransition spring1916 = trans.get(1);
313         assertEquals(spring1916.getDateTimeBefore(), LocalDateTime.of(1916, 5, 21, 2, 0));
314         assertEquals(spring1916.getOffsetBefore(), OFFSET_ZERO);
315         assertEquals(spring1916.getOffsetAfter(), OFFSET_PONE);
316 
317         ZoneOffsetTransition autumn1916 = trans.get(2);
318         assertEquals(autumn1916.getDateTimeBefore(), LocalDateTime.of(1916, 10, 1, 3, 0));
319         assertEquals(autumn1916.getOffsetBefore(), OFFSET_PONE);
320         assertEquals(autumn1916.getOffsetAfter(), OFFSET_ZERO);
321 
322         ZoneOffsetTransition zot = null;
323         Iterator<ZoneOffsetTransition> it = trans.iterator();
324         while (it.hasNext()) {
325             zot = it.next();
326             if (zot.getDateTimeBefore().getYear() == 1990) {
327                 break;
328             }
329         }
330         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1990, 3, 25, 1, 0));
331         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
332         zot = it.next();
333         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1990, 10, 28, 2, 0));
334         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
335         zot = it.next();
336         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1991, 3, 31, 1, 0));
337         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
338         zot = it.next();
339         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1991, 10, 27, 2, 0));
340         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
341         zot = it.next();
342         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1992, 3, 29, 1, 0));
343         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
344         zot = it.next();
345         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1992, 10, 25, 2, 0));
346         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
347         zot = it.next();
348         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1993, 3, 28, 1, 0));
349         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
350         zot = it.next();
351         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1993, 10, 24, 2, 0));
352         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
353         zot = it.next();
354         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1994, 3, 27, 1, 0));
355         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
356         zot = it.next();
357         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1994, 10, 23, 2, 0));
358         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
359         zot = it.next();
360         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1995, 3, 26, 1, 0));
361         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
362         zot = it.next();
363         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1995, 10, 22, 2, 0));
364         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
365         zot = it.next();
366         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1996, 3, 31, 1, 0));
367         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
368         zot = it.next();
369         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1996, 10, 27, 2, 0));
370         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
371         zot = it.next();
372         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1997, 3, 30, 1, 0));
373         assertEquals(zot.getOffsetBefore(), OFFSET_ZERO);
374         zot = it.next();
375         assertEquals(zot.getDateTimeBefore(), LocalDateTime.of(1997, 10, 26, 2, 0));
376         assertEquals(zot.getOffsetBefore(), OFFSET_PONE);
377         assertEquals(it.hasNext(), false);
378     }
379 
380     @Test
test_London_getTransitionRules()381     public void test_London_getTransitionRules() {
382         ZoneRules test = europeLondon();
383         List<ZoneOffsetTransitionRule> rules = test.getTransitionRules();
384         assertEquals(rules.size(), 2);
385 
386         ZoneOffsetTransitionRule in = rules.get(0);
387         assertEquals(in.getMonth(), Month.MARCH);
388         // Android-changed: check for -1, which matches the data, we don't do the "optimization"
389         assertEquals(in.getDayOfMonthIndicator(), -1);  // optimized from -1
390         assertEquals(in.getDayOfWeek(), DayOfWeek.SUNDAY);
391         assertEquals(in.getLocalTime(), LocalTime.of(1, 0));
392         assertEquals(in.getTimeDefinition(), TimeDefinition.UTC);
393         assertEquals(in.getStandardOffset(), OFFSET_ZERO);
394         assertEquals(in.getOffsetBefore(), OFFSET_ZERO);
395         assertEquals(in.getOffsetAfter(), OFFSET_PONE);
396 
397         ZoneOffsetTransitionRule out = rules.get(1);
398         assertEquals(out.getMonth(), Month.OCTOBER);
399         // Android-changed: check for -1, which matches the data, we don't do the "optimization"
400         assertEquals(out.getDayOfMonthIndicator(), -1);  // optimized from -1
401         assertEquals(out.getDayOfWeek(), DayOfWeek.SUNDAY);
402         assertEquals(out.getLocalTime(), LocalTime.of(1, 0));
403         assertEquals(out.getTimeDefinition(), TimeDefinition.UTC);
404         assertEquals(out.getStandardOffset(), OFFSET_ZERO);
405         assertEquals(out.getOffsetBefore(), OFFSET_PONE);
406         assertEquals(out.getOffsetAfter(), OFFSET_ZERO);
407     }
408 
409     //-----------------------------------------------------------------------
410     @Test
test_London_nextTransition_historic()411     public void test_London_nextTransition_historic() {
412         ZoneRules test = europeLondon();
413         List<ZoneOffsetTransition> trans = test.getTransitions();
414 
415         ZoneOffsetTransition first = trans.get(0);
416         assertEquals(test.nextTransition(first.getInstant().minusNanos(1)), first);
417 
418         for (int i = 0; i < trans.size() - 1; i++) {
419             ZoneOffsetTransition cur = trans.get(i);
420             ZoneOffsetTransition next = trans.get(i + 1);
421 
422             assertEquals(test.nextTransition(cur.getInstant()), next);
423             assertEquals(test.nextTransition(next.getInstant().minusNanos(1)), next);
424         }
425     }
426 
427     @Test
test_London_nextTransition_rulesBased()428     public void test_London_nextTransition_rulesBased() {
429         ZoneRules test = europeLondon();
430         List<ZoneOffsetTransitionRule> rules = test.getTransitionRules();
431         List<ZoneOffsetTransition> trans = test.getTransitions();
432 
433         ZoneOffsetTransition last = trans.get(trans.size() - 1);
434         assertEquals(test.nextTransition(last.getInstant()), rules.get(0).createTransition(1998));
435 
436         for (int year = 1998; year < 2010; year++) {
437             ZoneOffsetTransition a = rules.get(0).createTransition(year);
438             ZoneOffsetTransition b = rules.get(1).createTransition(year);
439             ZoneOffsetTransition c = rules.get(0).createTransition(year + 1);
440 
441             assertEquals(test.nextTransition(a.getInstant()), b);
442             assertEquals(test.nextTransition(b.getInstant().minusNanos(1)), b);
443 
444             assertEquals(test.nextTransition(b.getInstant()), c);
445             assertEquals(test.nextTransition(c.getInstant().minusNanos(1)), c);
446         }
447     }
448 
449     @Test
test_London_nextTransition_lastYear()450     public void test_London_nextTransition_lastYear() {
451         ZoneRules test = europeLondon();
452         List<ZoneOffsetTransitionRule> rules = test.getTransitionRules();
453         ZoneOffsetTransition zot = rules.get(1).createTransition(Year.MAX_VALUE);
454         assertEquals(test.nextTransition(zot.getInstant()), null);
455     }
456 
457     //-----------------------------------------------------------------------
458     @Test
test_London_previousTransition_historic()459     public void test_London_previousTransition_historic() {
460         ZoneRules test = europeLondon();
461         List<ZoneOffsetTransition> trans = test.getTransitions();
462 
463         ZoneOffsetTransition first = trans.get(0);
464         assertEquals(test.previousTransition(first.getInstant()), null);
465         assertEquals(test.previousTransition(first.getInstant().minusNanos(1)), null);
466 
467         for (int i = 0; i < trans.size() - 1; i++) {
468             ZoneOffsetTransition prev = trans.get(i);
469             ZoneOffsetTransition cur = trans.get(i + 1);
470 
471             assertEquals(test.previousTransition(cur.getInstant()), prev);
472             assertEquals(test.previousTransition(prev.getInstant().plusSeconds(1)), prev);
473             assertEquals(test.previousTransition(prev.getInstant().plusNanos(1)), prev);
474         }
475     }
476 
477     @Test
test_London_previousTransition_rulesBased()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     //-----------------------------------------------------------------------
europeParis()511     private ZoneRules europeParis() {
512         return ZoneId.of("Europe/Paris").getRules();
513     }
514 
515     @Test
test_Paris()516     public void test_Paris() {
517         ZoneRules test = europeParis();
518         assertEquals(test.isFixedOffset(), false);
519     }
520 
521     @Test
test_Paris_preTimeZones()522     public void test_Paris_preTimeZones() {
523         ZoneRules test = europeParis();
524         ZonedDateTime old = createZDT(1800, 1, 1, ZoneOffset.UTC);
525         Instant instant = old.toInstant();
526         ZoneOffset offset = ZoneOffset.ofHoursMinutesSeconds(0, 9, 21);
527         assertEquals(test.getOffset(instant), offset);
528         checkOffset(test, old.toLocalDateTime(), offset, 1);
529         assertEquals(test.getStandardOffset(instant), offset);
530         assertEquals(test.getDaylightSavings(instant), Duration.ZERO);
531         assertEquals(test.isDaylightSavings(instant), false);
532     }
533 
534     @Test
test_Paris_getOffset()535     public void test_Paris_getOffset() {
536         ZoneRules test = europeParis();
537         assertEquals(test.getOffset(createInstant(2008, 1, 1, ZoneOffset.UTC)), OFFSET_PONE);
538         assertEquals(test.getOffset(createInstant(2008, 2, 1, ZoneOffset.UTC)), OFFSET_PONE);
539         assertEquals(test.getOffset(createInstant(2008, 3, 1, ZoneOffset.UTC)), OFFSET_PONE);
540         assertEquals(test.getOffset(createInstant(2008, 4, 1, ZoneOffset.UTC)), OFFSET_PTWO);
541         assertEquals(test.getOffset(createInstant(2008, 5, 1, ZoneOffset.UTC)), OFFSET_PTWO);
542         assertEquals(test.getOffset(createInstant(2008, 6, 1, ZoneOffset.UTC)), OFFSET_PTWO);
543         assertEquals(test.getOffset(createInstant(2008, 7, 1, ZoneOffset.UTC)), OFFSET_PTWO);
544         assertEquals(test.getOffset(createInstant(2008, 8, 1, ZoneOffset.UTC)), OFFSET_PTWO);
545         assertEquals(test.getOffset(createInstant(2008, 9, 1, ZoneOffset.UTC)), OFFSET_PTWO);
546         assertEquals(test.getOffset(createInstant(2008, 10, 1, ZoneOffset.UTC)), OFFSET_PTWO);
547         assertEquals(test.getOffset(createInstant(2008, 11, 1, ZoneOffset.UTC)), OFFSET_PONE);
548         assertEquals(test.getOffset(createInstant(2008, 12, 1, ZoneOffset.UTC)), OFFSET_PONE);
549     }
550 
551     @Test
test_Paris_getOffset_toDST()552     public void test_Paris_getOffset_toDST() {
553         ZoneRules test = europeParis();
554         assertEquals(test.getOffset(createInstant(2008, 3, 24, ZoneOffset.UTC)), OFFSET_PONE);
555         assertEquals(test.getOffset(createInstant(2008, 3, 25, ZoneOffset.UTC)), OFFSET_PONE);
556         assertEquals(test.getOffset(createInstant(2008, 3, 26, ZoneOffset.UTC)), OFFSET_PONE);
557         assertEquals(test.getOffset(createInstant(2008, 3, 27, ZoneOffset.UTC)), OFFSET_PONE);
558         assertEquals(test.getOffset(createInstant(2008, 3, 28, ZoneOffset.UTC)), OFFSET_PONE);
559         assertEquals(test.getOffset(createInstant(2008, 3, 29, ZoneOffset.UTC)), OFFSET_PONE);
560         assertEquals(test.getOffset(createInstant(2008, 3, 30, ZoneOffset.UTC)), OFFSET_PONE);
561         assertEquals(test.getOffset(createInstant(2008, 3, 31, ZoneOffset.UTC)), OFFSET_PTWO);
562         // cutover at 01:00Z
563         assertEquals(test.getOffset(createInstant(2008, 3, 30, 0, 59, 59, 999999999, ZoneOffset.UTC)), OFFSET_PONE);
564         assertEquals(test.getOffset(createInstant(2008, 3, 30, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_PTWO);
565     }
566 
567     @Test
test_Paris_getOffset_fromDST()568     public void test_Paris_getOffset_fromDST() {
569         ZoneRules test = europeParis();
570         assertEquals(test.getOffset(createInstant(2008, 10, 24, ZoneOffset.UTC)), OFFSET_PTWO);
571         assertEquals(test.getOffset(createInstant(2008, 10, 25, ZoneOffset.UTC)), OFFSET_PTWO);
572         assertEquals(test.getOffset(createInstant(2008, 10, 26, ZoneOffset.UTC)), OFFSET_PTWO);
573         assertEquals(test.getOffset(createInstant(2008, 10, 27, ZoneOffset.UTC)), OFFSET_PONE);
574         assertEquals(test.getOffset(createInstant(2008, 10, 28, ZoneOffset.UTC)), OFFSET_PONE);
575         assertEquals(test.getOffset(createInstant(2008, 10, 29, ZoneOffset.UTC)), OFFSET_PONE);
576         assertEquals(test.getOffset(createInstant(2008, 10, 30, ZoneOffset.UTC)), OFFSET_PONE);
577         assertEquals(test.getOffset(createInstant(2008, 10, 31, ZoneOffset.UTC)), OFFSET_PONE);
578         // cutover at 01:00Z
579         assertEquals(test.getOffset(createInstant(2008, 10, 26, 0, 59, 59, 999999999, ZoneOffset.UTC)), OFFSET_PTWO);
580         assertEquals(test.getOffset(createInstant(2008, 10, 26, 1, 0, 0, 0, ZoneOffset.UTC)), OFFSET_PONE);
581     }
582 
583     @Test
test_Paris_getOffsetInfo()584     public void test_Paris_getOffsetInfo() {
585         ZoneRules test = europeParis();
586         checkOffset(test, createLDT(2008, 1, 1), OFFSET_PONE, 1);
587         checkOffset(test, createLDT(2008, 2, 1), OFFSET_PONE, 1);
588         checkOffset(test, createLDT(2008, 3, 1), OFFSET_PONE, 1);
589         checkOffset(test, createLDT(2008, 4, 1), OFFSET_PTWO, 1);
590         checkOffset(test, createLDT(2008, 5, 1), OFFSET_PTWO, 1);
591         checkOffset(test, createLDT(2008, 6, 1), OFFSET_PTWO, 1);
592         checkOffset(test, createLDT(2008, 7, 1), OFFSET_PTWO, 1);
593         checkOffset(test, createLDT(2008, 8, 1), OFFSET_PTWO, 1);
594         checkOffset(test, createLDT(2008, 9, 1), OFFSET_PTWO, 1);
595         checkOffset(test, createLDT(2008, 10, 1), OFFSET_PTWO, 1);
596         checkOffset(test, createLDT(2008, 11, 1), OFFSET_PONE, 1);
597         checkOffset(test, createLDT(2008, 12, 1), OFFSET_PONE, 1);
598     }
599 
600     @Test
test_Paris_getOffsetInfo_toDST()601     public void test_Paris_getOffsetInfo_toDST() {
602         ZoneRules test = europeParis();
603         checkOffset(test, createLDT(2008, 3, 24), OFFSET_PONE, 1);
604         checkOffset(test, createLDT(2008, 3, 25), OFFSET_PONE, 1);
605         checkOffset(test, createLDT(2008, 3, 26), OFFSET_PONE, 1);
606         checkOffset(test, createLDT(2008, 3, 27), OFFSET_PONE, 1);
607         checkOffset(test, createLDT(2008, 3, 28), OFFSET_PONE, 1);
608         checkOffset(test, createLDT(2008, 3, 29), OFFSET_PONE, 1);
609         checkOffset(test, createLDT(2008, 3, 30), OFFSET_PONE, 1);
610         checkOffset(test, createLDT(2008, 3, 31), OFFSET_PTWO, 1);
611         // cutover at 01:00Z which is 02:00+01:00(local Paris time)
612         checkOffset(test, LocalDateTime.of(2008, 3, 30, 1, 59, 59, 999999999), OFFSET_PONE, 1);
613         checkOffset(test, LocalDateTime.of(2008, 3, 30, 3, 0, 0, 0), OFFSET_PTWO, 1);
614     }
615 
616     @Test
test_Paris_getOffsetInfo_fromDST()617     public void test_Paris_getOffsetInfo_fromDST() {
618         ZoneRules test = europeParis();
619         checkOffset(test, createLDT(2008, 10, 24), OFFSET_PTWO, 1);
620         checkOffset(test, createLDT(2008, 10, 25), OFFSET_PTWO, 1);
621         checkOffset(test, createLDT(2008, 10, 26), OFFSET_PTWO, 1);
622         checkOffset(test, createLDT(2008, 10, 27), OFFSET_PONE, 1);
623         checkOffset(test, createLDT(2008, 10, 28), OFFSET_PONE, 1);
624         checkOffset(test, createLDT(2008, 10, 29), OFFSET_PONE, 1);
625         checkOffset(test, createLDT(2008, 10, 30), OFFSET_PONE, 1);
626         checkOffset(test, createLDT(2008, 10, 31), OFFSET_PONE, 1);
627         // cutover at 01:00Z which is 02:00+01:00(local Paris time)
628         checkOffset(test, LocalDateTime.of(2008, 10, 26, 1, 59, 59, 999999999), OFFSET_PTWO, 1);
629         checkOffset(test, LocalDateTime.of(2008, 10, 26, 3, 0, 0, 0), OFFSET_PONE, 1);
630     }
631 
632     @Test
test_Paris_getOffsetInfo_gap()633     public void test_Paris_getOffsetInfo_gap() {
634         ZoneRules test = europeParis();
635         final LocalDateTime dateTime = LocalDateTime.of(2008, 3, 30, 2, 0, 0, 0);
636         ZoneOffsetTransition trans = checkOffset(test, dateTime, OFFSET_PONE, GAP);
637         assertEquals(trans.isGap(), true);
638         assertEquals(trans.isOverlap(), false);
639         assertEquals(trans.getOffsetBefore(), OFFSET_PONE);
640         assertEquals(trans.getOffsetAfter(), OFFSET_PTWO);
641         assertEquals(trans.getInstant(), createInstant(2008, 3, 30, 1, 0, ZoneOffset.UTC));
642         assertEquals(trans.isValidOffset(OFFSET_ZERO), false);
643         assertEquals(trans.isValidOffset(OFFSET_PONE), false);
644         assertEquals(trans.isValidOffset(OFFSET_PTWO), false);
645         assertEquals(trans.toString(), "Transition[Gap at 2008-03-30T02:00+01:00 to +02:00]");
646 
647         assertFalse(trans.equals(null));
648         assertFalse(trans.equals(OFFSET_PONE));
649         assertTrue(trans.equals(trans));
650 
651         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
652         assertTrue(trans.equals(otherTrans));
653         assertEquals(trans.hashCode(), otherTrans.hashCode());
654     }
655 
656     @Test
test_Paris_getOffsetInfo_overlap()657     public void test_Paris_getOffsetInfo_overlap() {
658         ZoneRules test = europeParis();
659         final LocalDateTime dateTime = LocalDateTime.of(2008, 10, 26, 2, 0, 0, 0);
660         ZoneOffsetTransition trans = checkOffset(test, dateTime, OFFSET_PTWO, OVERLAP);
661         assertEquals(trans.isGap(), false);
662         assertEquals(trans.isOverlap(), true);
663         assertEquals(trans.getOffsetBefore(), OFFSET_PTWO);
664         assertEquals(trans.getOffsetAfter(), OFFSET_PONE);
665         assertEquals(trans.getInstant(), createInstant(2008, 10, 26, 1, 0, ZoneOffset.UTC));
666         assertEquals(trans.isValidOffset(OFFSET_ZERO), false);
667         assertEquals(trans.isValidOffset(OFFSET_PONE), true);
668         assertEquals(trans.isValidOffset(OFFSET_PTWO), true);
669         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(3)), false);
670         assertEquals(trans.toString(), "Transition[Overlap at 2008-10-26T03:00+02:00 to +01:00]");
671 
672         assertFalse(trans.equals(null));
673         assertFalse(trans.equals(OFFSET_PTWO));
674         assertTrue(trans.equals(trans));
675 
676         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
677         assertTrue(trans.equals(otherTrans));
678         assertEquals(trans.hashCode(), otherTrans.hashCode());
679     }
680 
681     @Test
test_Paris_getStandardOffset()682     public void test_Paris_getStandardOffset() {
683         ZoneRules test = europeParis();
684         ZonedDateTime zdt = createZDT(1840, 1, 1, ZoneOffset.UTC);
685         while (zdt.getYear() < 2010) {
686             Instant instant = zdt.toInstant();
687             if (zdt.toLocalDate().isBefore(LocalDate.of(1911, 3, 11))) {
688                 assertEquals(test.getStandardOffset(instant), ZoneOffset.ofHoursMinutesSeconds(0, 9, 21));
689             } else if (zdt.toLocalDate().isBefore(LocalDate.of(1940, 6, 14))) {
690                 assertEquals(test.getStandardOffset(instant), OFFSET_ZERO);
691             } else if (zdt.toLocalDate().isBefore(LocalDate.of(1944, 8, 25))) {
692                 assertEquals(test.getStandardOffset(instant), OFFSET_PONE);
693             } else if (zdt.toLocalDate().isBefore(LocalDate.of(1945, 9, 16))) {
694                 assertEquals(test.getStandardOffset(instant), OFFSET_ZERO);
695             } else {
696                 assertEquals(test.getStandardOffset(instant), OFFSET_PONE);
697             }
698             zdt = zdt.plusMonths(6);
699         }
700     }
701 
702     //-----------------------------------------------------------------------
703     // America/New_York
704     //-----------------------------------------------------------------------
americaNewYork()705     private ZoneRules americaNewYork() {
706         return ZoneId.of("America/New_York").getRules();
707     }
708 
709     @Test
test_NewYork()710     public void test_NewYork() {
711         ZoneRules test = americaNewYork();
712         assertEquals(test.isFixedOffset(), false);
713     }
714 
715     @Test
test_NewYork_preTimeZones()716     public void test_NewYork_preTimeZones() {
717         ZoneRules test = americaNewYork();
718         ZonedDateTime old = createZDT(1800, 1, 1, ZoneOffset.UTC);
719         Instant instant = old.toInstant();
720         ZoneOffset offset = ZoneOffset.of("-04:56:02");
721         assertEquals(test.getOffset(instant), offset);
722         checkOffset(test, old.toLocalDateTime(), offset, 1);
723         assertEquals(test.getStandardOffset(instant), offset);
724         assertEquals(test.getDaylightSavings(instant), Duration.ZERO);
725         assertEquals(test.isDaylightSavings(instant), false);
726     }
727 
728     @Test
test_NewYork_getOffset()729     public void test_NewYork_getOffset() {
730         ZoneRules test = americaNewYork();
731         ZoneOffset offset = ZoneOffset.ofHours(-5);
732         assertEquals(test.getOffset(createInstant(2008, 1, 1, offset)), ZoneOffset.ofHours(-5));
733         assertEquals(test.getOffset(createInstant(2008, 2, 1, offset)), ZoneOffset.ofHours(-5));
734         assertEquals(test.getOffset(createInstant(2008, 3, 1, offset)), ZoneOffset.ofHours(-5));
735         assertEquals(test.getOffset(createInstant(2008, 4, 1, offset)), ZoneOffset.ofHours(-4));
736         assertEquals(test.getOffset(createInstant(2008, 5, 1, offset)), ZoneOffset.ofHours(-4));
737         assertEquals(test.getOffset(createInstant(2008, 6, 1, offset)), ZoneOffset.ofHours(-4));
738         assertEquals(test.getOffset(createInstant(2008, 7, 1, offset)), ZoneOffset.ofHours(-4));
739         assertEquals(test.getOffset(createInstant(2008, 8, 1, offset)), ZoneOffset.ofHours(-4));
740         assertEquals(test.getOffset(createInstant(2008, 9, 1, offset)), ZoneOffset.ofHours(-4));
741         assertEquals(test.getOffset(createInstant(2008, 10, 1, offset)), ZoneOffset.ofHours(-4));
742         assertEquals(test.getOffset(createInstant(2008, 11, 1, offset)), ZoneOffset.ofHours(-4));
743         assertEquals(test.getOffset(createInstant(2008, 12, 1, offset)), ZoneOffset.ofHours(-5));
744         assertEquals(test.getOffset(createInstant(2008, 1, 28, offset)), ZoneOffset.ofHours(-5));
745         assertEquals(test.getOffset(createInstant(2008, 2, 28, offset)), ZoneOffset.ofHours(-5));
746         assertEquals(test.getOffset(createInstant(2008, 3, 28, offset)), ZoneOffset.ofHours(-4));
747         assertEquals(test.getOffset(createInstant(2008, 4, 28, offset)), ZoneOffset.ofHours(-4));
748         assertEquals(test.getOffset(createInstant(2008, 5, 28, offset)), ZoneOffset.ofHours(-4));
749         assertEquals(test.getOffset(createInstant(2008, 6, 28, offset)), ZoneOffset.ofHours(-4));
750         assertEquals(test.getOffset(createInstant(2008, 7, 28, offset)), ZoneOffset.ofHours(-4));
751         assertEquals(test.getOffset(createInstant(2008, 8, 28, offset)), ZoneOffset.ofHours(-4));
752         assertEquals(test.getOffset(createInstant(2008, 9, 28, offset)), ZoneOffset.ofHours(-4));
753         assertEquals(test.getOffset(createInstant(2008, 10, 28, offset)), ZoneOffset.ofHours(-4));
754         assertEquals(test.getOffset(createInstant(2008, 11, 28, offset)), ZoneOffset.ofHours(-5));
755         assertEquals(test.getOffset(createInstant(2008, 12, 28, offset)), ZoneOffset.ofHours(-5));
756     }
757 
758     @Test
test_NewYork_getOffset_toDST()759     public void test_NewYork_getOffset_toDST() {
760         ZoneRules test = americaNewYork();
761         ZoneOffset offset = ZoneOffset.ofHours(-5);
762         assertEquals(test.getOffset(createInstant(2008, 3, 8, offset)), ZoneOffset.ofHours(-5));
763         assertEquals(test.getOffset(createInstant(2008, 3, 9, offset)), ZoneOffset.ofHours(-5));
764         assertEquals(test.getOffset(createInstant(2008, 3, 10, offset)), ZoneOffset.ofHours(-4));
765         assertEquals(test.getOffset(createInstant(2008, 3, 11, offset)), ZoneOffset.ofHours(-4));
766         assertEquals(test.getOffset(createInstant(2008, 3, 12, offset)), ZoneOffset.ofHours(-4));
767         assertEquals(test.getOffset(createInstant(2008, 3, 13, offset)), ZoneOffset.ofHours(-4));
768         assertEquals(test.getOffset(createInstant(2008, 3, 14, offset)), ZoneOffset.ofHours(-4));
769         // cutover at 02:00 local
770         assertEquals(test.getOffset(createInstant(2008, 3, 9, 1, 59, 59, 999999999, offset)), ZoneOffset.ofHours(-5));
771         assertEquals(test.getOffset(createInstant(2008, 3, 9, 2, 0, 0, 0, offset)), ZoneOffset.ofHours(-4));
772     }
773 
774     @Test
test_NewYork_getOffset_fromDST()775     public void test_NewYork_getOffset_fromDST() {
776         ZoneRules test = americaNewYork();
777         ZoneOffset offset = ZoneOffset.ofHours(-4);
778         assertEquals(test.getOffset(createInstant(2008, 11, 1, offset)), ZoneOffset.ofHours(-4));
779         assertEquals(test.getOffset(createInstant(2008, 11, 2, offset)), ZoneOffset.ofHours(-4));
780         assertEquals(test.getOffset(createInstant(2008, 11, 3, offset)), ZoneOffset.ofHours(-5));
781         assertEquals(test.getOffset(createInstant(2008, 11, 4, offset)), ZoneOffset.ofHours(-5));
782         assertEquals(test.getOffset(createInstant(2008, 11, 5, offset)), ZoneOffset.ofHours(-5));
783         assertEquals(test.getOffset(createInstant(2008, 11, 6, offset)), ZoneOffset.ofHours(-5));
784         assertEquals(test.getOffset(createInstant(2008, 11, 7, offset)), ZoneOffset.ofHours(-5));
785         // cutover at 02:00 local
786         assertEquals(test.getOffset(createInstant(2008, 11, 2, 1, 59, 59, 999999999, offset)), ZoneOffset.ofHours(-4));
787         assertEquals(test.getOffset(createInstant(2008, 11, 2, 2, 0, 0, 0, offset)), ZoneOffset.ofHours(-5));
788     }
789 
790     @Test
test_NewYork_getOffsetInfo()791     public void test_NewYork_getOffsetInfo() {
792         ZoneRules test = americaNewYork();
793         checkOffset(test, createLDT(2008, 1, 1), ZoneOffset.ofHours(-5), 1);
794         checkOffset(test, createLDT(2008, 2, 1), ZoneOffset.ofHours(-5), 1);
795         checkOffset(test, createLDT(2008, 3, 1), ZoneOffset.ofHours(-5), 1);
796         checkOffset(test, createLDT(2008, 4, 1), ZoneOffset.ofHours(-4), 1);
797         checkOffset(test, createLDT(2008, 5, 1), ZoneOffset.ofHours(-4), 1);
798         checkOffset(test, createLDT(2008, 6, 1), ZoneOffset.ofHours(-4), 1);
799         checkOffset(test, createLDT(2008, 7, 1), ZoneOffset.ofHours(-4), 1);
800         checkOffset(test, createLDT(2008, 8, 1), ZoneOffset.ofHours(-4), 1);
801         checkOffset(test, createLDT(2008, 9, 1), ZoneOffset.ofHours(-4), 1);
802         checkOffset(test, createLDT(2008, 10, 1), ZoneOffset.ofHours(-4), 1);
803         checkOffset(test, createLDT(2008, 11, 1), ZoneOffset.ofHours(-4), 1);
804         checkOffset(test, createLDT(2008, 12, 1), ZoneOffset.ofHours(-5), 1);
805         checkOffset(test, createLDT(2008, 1, 28), ZoneOffset.ofHours(-5), 1);
806         checkOffset(test, createLDT(2008, 2, 28), ZoneOffset.ofHours(-5), 1);
807         checkOffset(test, createLDT(2008, 3, 28), ZoneOffset.ofHours(-4), 1);
808         checkOffset(test, createLDT(2008, 4, 28), ZoneOffset.ofHours(-4), 1);
809         checkOffset(test, createLDT(2008, 5, 28), ZoneOffset.ofHours(-4), 1);
810         checkOffset(test, createLDT(2008, 6, 28), ZoneOffset.ofHours(-4), 1);
811         checkOffset(test, createLDT(2008, 7, 28), ZoneOffset.ofHours(-4), 1);
812         checkOffset(test, createLDT(2008, 8, 28), ZoneOffset.ofHours(-4), 1);
813         checkOffset(test, createLDT(2008, 9, 28), ZoneOffset.ofHours(-4), 1);
814         checkOffset(test, createLDT(2008, 10, 28), ZoneOffset.ofHours(-4), 1);
815         checkOffset(test, createLDT(2008, 11, 28), ZoneOffset.ofHours(-5), 1);
816         checkOffset(test, createLDT(2008, 12, 28), ZoneOffset.ofHours(-5), 1);
817     }
818 
819     @Test
test_NewYork_getOffsetInfo_toDST()820     public void test_NewYork_getOffsetInfo_toDST() {
821         ZoneRules test = americaNewYork();
822         checkOffset(test, createLDT(2008, 3, 8), ZoneOffset.ofHours(-5), 1);
823         checkOffset(test, createLDT(2008, 3, 9), ZoneOffset.ofHours(-5), 1);
824         checkOffset(test, createLDT(2008, 3, 10), ZoneOffset.ofHours(-4), 1);
825         checkOffset(test, createLDT(2008, 3, 11), ZoneOffset.ofHours(-4), 1);
826         checkOffset(test, createLDT(2008, 3, 12), ZoneOffset.ofHours(-4), 1);
827         checkOffset(test, createLDT(2008, 3, 13), ZoneOffset.ofHours(-4), 1);
828         checkOffset(test, createLDT(2008, 3, 14), ZoneOffset.ofHours(-4), 1);
829         // cutover at 02:00 local
830         checkOffset(test, LocalDateTime.of(2008, 3, 9, 1, 59, 59, 999999999), ZoneOffset.ofHours(-5), 1);
831         checkOffset(test, LocalDateTime.of(2008, 3, 9, 3, 0, 0, 0), ZoneOffset.ofHours(-4), 1);
832     }
833 
834     @Test
test_NewYork_getOffsetInfo_fromDST()835     public void test_NewYork_getOffsetInfo_fromDST() {
836         ZoneRules test = americaNewYork();
837         checkOffset(test, createLDT(2008, 11, 1), ZoneOffset.ofHours(-4), 1);
838         checkOffset(test, createLDT(2008, 11, 2), ZoneOffset.ofHours(-4), 1);
839         checkOffset(test, createLDT(2008, 11, 3), ZoneOffset.ofHours(-5), 1);
840         checkOffset(test, createLDT(2008, 11, 4), ZoneOffset.ofHours(-5), 1);
841         checkOffset(test, createLDT(2008, 11, 5), ZoneOffset.ofHours(-5), 1);
842         checkOffset(test, createLDT(2008, 11, 6), ZoneOffset.ofHours(-5), 1);
843         checkOffset(test, createLDT(2008, 11, 7), ZoneOffset.ofHours(-5), 1);
844         // cutover at 02:00 local
845         checkOffset(test, LocalDateTime.of(2008, 11, 2, 0, 59, 59, 999999999), ZoneOffset.ofHours(-4), 1);
846         checkOffset(test, LocalDateTime.of(2008, 11, 2, 2, 0, 0, 0), ZoneOffset.ofHours(-5), 1);
847     }
848 
849     @Test
test_NewYork_getOffsetInfo_gap()850     public void test_NewYork_getOffsetInfo_gap() {
851         ZoneRules test = americaNewYork();
852         final LocalDateTime dateTime = LocalDateTime.of(2008, 3, 9, 2, 0, 0, 0);
853         ZoneOffsetTransition trans = checkOffset(test, dateTime, ZoneOffset.ofHours(-5), GAP);
854         assertEquals(trans.isGap(), true);
855         assertEquals(trans.isOverlap(), false);
856         assertEquals(trans.getOffsetBefore(), ZoneOffset.ofHours(-5));
857         assertEquals(trans.getOffsetAfter(), ZoneOffset.ofHours(-4));
858         assertEquals(trans.getInstant(), createInstant(2008, 3, 9, 2, 0, ZoneOffset.ofHours(-5)));
859         assertEquals(trans.isValidOffset(OFFSET_PTWO), false);
860         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-5)), false);
861         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-4)), false);
862         assertEquals(trans.toString(), "Transition[Gap at 2008-03-09T02:00-05:00 to -04:00]");
863 
864         assertFalse(trans.equals(null));
865         assertFalse(trans.equals(ZoneOffset.ofHours(-5)));
866         assertTrue(trans.equals(trans));
867 
868         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
869         assertTrue(trans.equals(otherTrans));
870         assertEquals(trans.hashCode(), otherTrans.hashCode());
871     }
872 
873     @Test
test_NewYork_getOffsetInfo_overlap()874     public void test_NewYork_getOffsetInfo_overlap() {
875         ZoneRules test = americaNewYork();
876         final LocalDateTime dateTime = LocalDateTime.of(2008, 11, 2, 1, 0, 0, 0);
877         ZoneOffsetTransition trans = checkOffset(test, dateTime, ZoneOffset.ofHours(-4), OVERLAP);
878         assertEquals(trans.isGap(), false);
879         assertEquals(trans.isOverlap(), true);
880         assertEquals(trans.getOffsetBefore(), ZoneOffset.ofHours(-4));
881         assertEquals(trans.getOffsetAfter(), ZoneOffset.ofHours(-5));
882         assertEquals(trans.getInstant(), createInstant(2008, 11, 2, 2, 0, ZoneOffset.ofHours(-4)));
883         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-1)), false);
884         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-5)), true);
885         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-4)), true);
886         assertEquals(trans.isValidOffset(OFFSET_PTWO), false);
887         assertEquals(trans.toString(), "Transition[Overlap at 2008-11-02T02:00-04:00 to -05:00]");
888 
889         assertFalse(trans.equals(null));
890         assertFalse(trans.equals(ZoneOffset.ofHours(-4)));
891         assertTrue(trans.equals(trans));
892 
893         final ZoneOffsetTransition otherTrans = test.getTransition(dateTime);
894         assertTrue(trans.equals(otherTrans));
895         assertEquals(trans.hashCode(), otherTrans.hashCode());
896     }
897 
898     @Test
test_NewYork_getStandardOffset()899     public void test_NewYork_getStandardOffset() {
900         ZoneRules test = americaNewYork();
901         ZonedDateTime dateTime = createZDT(1860, 1, 1, ZoneOffset.UTC);
902         while (dateTime.getYear() < 2010) {
903             Instant instant = dateTime.toInstant();
904             if (dateTime.toLocalDate().isBefore(LocalDate.of(1883, 11, 18))) {
905                 assertEquals(test.getStandardOffset(instant), ZoneOffset.of("-04:56:02"));
906             } else {
907                 assertEquals(test.getStandardOffset(instant), ZoneOffset.ofHours(-5));
908             }
909             dateTime = dateTime.plusMonths(6);
910         }
911     }
912 
913     //-----------------------------------------------------------------------
914     // Kathmandu
915     //-----------------------------------------------------------------------
asiaKathmandu()916     private ZoneRules asiaKathmandu() {
917         return ZoneId.of("Asia/Kathmandu").getRules();
918     }
919 
920     @Test
test_Kathmandu_nextTransition_historic()921     public void test_Kathmandu_nextTransition_historic() {
922         ZoneRules test = asiaKathmandu();
923         List<ZoneOffsetTransition> trans = test.getTransitions();
924 
925         ZoneOffsetTransition first = trans.get(0);
926         assertEquals(test.nextTransition(first.getInstant().minusNanos(1)), first);
927 
928         for (int i = 0; i < trans.size() - 1; i++) {
929             ZoneOffsetTransition cur = trans.get(i);
930             ZoneOffsetTransition next = trans.get(i + 1);
931 
932             assertEquals(test.nextTransition(cur.getInstant()), next);
933             assertEquals(test.nextTransition(next.getInstant().minusNanos(1)), next);
934         }
935     }
936 
937     @Test
test_Kathmandu_nextTransition_noRules()938     public void test_Kathmandu_nextTransition_noRules() {
939         ZoneRules test = asiaKathmandu();
940         List<ZoneOffsetTransition> trans = test.getTransitions();
941 
942         ZoneOffsetTransition last = trans.get(trans.size() - 1);
943         assertEquals(test.nextTransition(last.getInstant()), null);
944     }
945 
946     //-----------------------------------------------------------------------
947     // Apia
948     //-----------------------------------------------------------------------
pacificApia()949     private ZoneRules pacificApia() {
950         return ZoneId.of("Pacific/Apia").getRules();
951     }
952 
953     @Test
test_Apia_nextTransition_historic()954     public void test_Apia_nextTransition_historic() {
955         ZoneRules test = pacificApia();
956         List<ZoneOffsetTransition> trans = test.getTransitions();
957 
958         ZoneOffsetTransition first = trans.get(0);
959         assertEquals(test.nextTransition(first.getInstant().minusNanos(1)), first);
960 
961         for (int i = 0; i < trans.size() - 1; i++) {
962             ZoneOffsetTransition cur = trans.get(i);
963             ZoneOffsetTransition next = trans.get(i + 1);
964 
965             assertEquals(test.nextTransition(cur.getInstant()), next);
966             assertEquals(test.nextTransition(next.getInstant().minusNanos(1)), next);
967         }
968     }
969 
970     @Test
test_Apia_jumpOverInternationalDateLine_M10_to_P14()971     public void test_Apia_jumpOverInternationalDateLine_M10_to_P14() {
972         // transition occurred at 2011-12-30T00:00-10:00
973         ZoneRules test = pacificApia();
974         Instant instantBefore = LocalDate.of(2011, 12, 27).atStartOfDay(ZoneOffset.UTC).toInstant();
975         ZoneOffsetTransition trans = test.nextTransition(instantBefore);
976         assertEquals(trans.getDateTimeBefore(), LocalDateTime.of(2011, 12, 30, 0, 0));
977         assertEquals(trans.getDateTimeAfter(), LocalDateTime.of(2011, 12, 31, 0, 0));
978         assertEquals(trans.isGap(), true);
979         assertEquals(trans.isOverlap(), false);
980         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(-10)), false);
981         assertEquals(trans.isValidOffset(ZoneOffset.ofHours(+14)), false);
982         assertEquals(trans.getDuration(), Duration.ofHours(24));
983         assertEquals(trans.getInstant(), LocalDateTime.of(2011, 12, 31, 0, 0).toInstant(ZoneOffset.ofHours(+14)));
984 
985         ZonedDateTime zdt = ZonedDateTime.of(2011, 12, 29, 23, 0, 0, 0, ZoneId.of("Pacific/Apia"));
986         assertEquals(zdt.plusHours(2).toLocalDateTime(), LocalDateTime.of(2011, 12, 31, 1, 0));
987     }
988 
989     @Test
test_Apia_jumpForwardOverInternationalDateLine_P12_to_M12()990     public void test_Apia_jumpForwardOverInternationalDateLine_P12_to_M12() {
991         // transition occurred at 1892-07-04T00:00+12:33:04
992         ZoneRules test = pacificApia();
993         Instant instantBefore = LocalDate.of(1892, 7, 2).atStartOfDay(ZoneOffset.UTC).toInstant();
994         ZoneOffsetTransition trans = test.nextTransition(instantBefore);
995         assertEquals(trans.getDateTimeBefore(), LocalDateTime.of(1892, 7, 5, 0, 0));
996         assertEquals(trans.getDateTimeAfter(), LocalDateTime.of(1892, 7, 4, 0, 0));
997         assertEquals(trans.isGap(), false);
998         assertEquals(trans.isOverlap(), true);
999         assertEquals(trans.isValidOffset(ZoneOffset.ofHoursMinutesSeconds(+12, 33, 4)), true);
1000         assertEquals(trans.isValidOffset(ZoneOffset.ofHoursMinutesSeconds(-11, -26, -56)), true);
1001         assertEquals(trans.getDuration(), Duration.ofHours(-24));
1002         assertEquals(trans.getInstant(), LocalDateTime.of(1892, 7, 4, 0, 0).toInstant(ZoneOffset.ofHoursMinutesSeconds(-11, -26, -56)));
1003 
1004         ZonedDateTime zdt = ZonedDateTime.of(1892, 7, 4, 23, 0, 0, 0, ZoneId.of("Pacific/Apia"));
1005         assertEquals(zdt.plusHours(2).toLocalDateTime(), LocalDateTime.of(1892, 7, 4, 1, 0, 0));
1006     }
1007 
1008     //-------------------------------------------------------------------------
1009     @Test(expectedExceptions=UnsupportedOperationException.class)
test_getTransitions_immutable()1010     public void test_getTransitions_immutable() {
1011         ZoneRules test = europeParis();
1012         test.getTransitions().clear();
1013     }
1014 
1015     @Test(expectedExceptions=UnsupportedOperationException.class)
test_getTransitionRules_immutable()1016     public void test_getTransitionRules_immutable() {
1017         ZoneRules test = europeParis();
1018         test.getTransitionRules().clear();
1019     }
1020 
1021     //-----------------------------------------------------------------------
1022     // of()
1023     //-----------------------------------------------------------------------
1024     @Test
test_of()1025     public void test_of(){
1026         //used for standard offset
1027         ZoneOffset stdOffset1 = ZoneOffset.UTC;
1028         ZoneOffset stdOffset2 = ZoneOffset.ofHours(1);
1029         LocalDateTime time_of_stdOffsetTransition1 = LocalDateTime.of(2013, 1, 5, 1, 0);
1030         ZoneOffsetTransition  stdOffsetTransition1 = ZoneOffsetTransition.of(time_of_stdOffsetTransition1, stdOffset1, stdOffset2);
1031         List<ZoneOffsetTransition> stdOffsetTransition_list = new ArrayList<ZoneOffsetTransition>();
1032         stdOffsetTransition_list.add(stdOffsetTransition1);
1033 
1034         //used for wall offset
1035         ZoneOffset wallOffset1 = ZoneOffset.ofHours(2);
1036         ZoneOffset wallOffset2 = ZoneOffset.ofHours(4);
1037         ZoneOffset wallOffset3 = ZoneOffset.ofHours(7);
1038 
1039         LocalDateTime time_of_wallOffsetTransition1 = LocalDateTime.of(2013, 2, 5, 1, 0);
1040         LocalDateTime time_of_wallOffsetTransition2 = LocalDateTime.of(2013, 3, 5, 1, 0);
1041         LocalDateTime time_of_wallOffsetTransition3 = LocalDateTime.of(2013, 10, 5, 1, 0);
1042 
1043         ZoneOffsetTransition  wallOffsetTransition1 = ZoneOffsetTransition.of(time_of_wallOffsetTransition1, wallOffset1, wallOffset2);
1044         ZoneOffsetTransition  wallOffsetTransition2 = ZoneOffsetTransition.of(time_of_wallOffsetTransition2, wallOffset2, wallOffset3);
1045         ZoneOffsetTransition  wallOffsetTransition3 = ZoneOffsetTransition.of(time_of_wallOffsetTransition3, wallOffset3, wallOffset1);
1046 
1047         List<ZoneOffsetTransition> wallOffsetTransition_list = new ArrayList<ZoneOffsetTransition>();
1048         wallOffsetTransition_list.add(wallOffsetTransition1);
1049         wallOffsetTransition_list.add(wallOffsetTransition2);
1050         wallOffsetTransition_list.add(wallOffsetTransition3);
1051 
1052         //used for ZoneOffsetTransitionRule
1053         ZoneOffset ruleOffset = ZoneOffset.ofHours(3);
1054         ZoneOffsetTransitionRule.TimeDefinition timeDefinition = ZoneOffsetTransitionRule.TimeDefinition.valueOf("WALL");
1055         ZoneOffsetTransitionRule rule1 = ZoneOffsetTransitionRule.of(Month.FEBRUARY,
1056                                                                      2,
1057                                                                      DayOfWeek.MONDAY,
1058                                                                      LocalTime.of(1, 0),
1059                                                                      false,
1060                                                                      timeDefinition,
1061                                                                      ZoneOffset.UTC,
1062                                                                      ZoneOffset.UTC,
1063                                                                      ruleOffset
1064                                                                      );
1065          List<ZoneOffsetTransitionRule> rule_list = new ArrayList<ZoneOffsetTransitionRule>();
1066          rule_list.add(rule1);
1067 
1068          //Begin verification
1069          ZoneRules zoneRule = ZoneRules.of(stdOffset1,
1070                                            wallOffset1,
1071                                            stdOffsetTransition_list,
1072                                            wallOffsetTransition_list,
1073                                            rule_list
1074                                            );
1075 
1076          OffsetDateTime before_time_of_stdOffsetTransition1 = OffsetDateTime.of(time_of_stdOffsetTransition1, stdOffset1).minusSeconds(1);
1077          OffsetDateTime after_time_of_stdOffsetTransition1 = OffsetDateTime.of(time_of_stdOffsetTransition1, stdOffset1).plusSeconds(1);;
1078          assertEquals(zoneRule.getStandardOffset(before_time_of_stdOffsetTransition1.toInstant()), stdOffset1);
1079          assertEquals(zoneRule.getStandardOffset(after_time_of_stdOffsetTransition1.toInstant()), stdOffset2);
1080 
1081          OffsetDateTime  before_time_of_wallOffsetTransition1 = OffsetDateTime.of(time_of_wallOffsetTransition1, wallOffset1).minusSeconds(1);
1082          OffsetDateTime  after_time_of_wallOffsetTransition1 = OffsetDateTime.of(time_of_wallOffsetTransition1, wallOffset1).plusSeconds(1);
1083          assertEquals(zoneRule.nextTransition(before_time_of_wallOffsetTransition1.toInstant()), wallOffsetTransition1);
1084          assertEquals(zoneRule.nextTransition(after_time_of_wallOffsetTransition1.toInstant()), wallOffsetTransition2);
1085 
1086          OffsetDateTime  before_time_of_wallOffsetTransition2 = OffsetDateTime.of(time_of_wallOffsetTransition2, wallOffset2).minusSeconds(1);
1087          OffsetDateTime  after_time_of_wallOffsetTransition2 = OffsetDateTime.of(time_of_wallOffsetTransition2, wallOffset2).plusSeconds(1);
1088          assertEquals(zoneRule.nextTransition(before_time_of_wallOffsetTransition2.toInstant()), wallOffsetTransition2);
1089          assertEquals(zoneRule.nextTransition(after_time_of_wallOffsetTransition2.toInstant()), wallOffsetTransition3);
1090 
1091          OffsetDateTime  before_time_of_wallOffsetTransition3 = OffsetDateTime.of(time_of_wallOffsetTransition3, wallOffset3).minusSeconds(1);
1092          OffsetDateTime  after_time_of_wallOffsetTransition3 = OffsetDateTime.of(time_of_wallOffsetTransition3, wallOffset3).plusSeconds(1);
1093          assertEquals(zoneRule.nextTransition(before_time_of_wallOffsetTransition3.toInstant()), wallOffsetTransition3);
1094          assertEquals(zoneRule.nextTransition(after_time_of_wallOffsetTransition3.toInstant()), rule1.createTransition(2014));
1095     }
1096 
1097     //-----------------------------------------------------------------------
1098     // equals() / hashCode()
1099     //-----------------------------------------------------------------------
1100     @Test
test_equals()1101     public void test_equals() {
1102         ZoneRules test1 = europeLondon();
1103         ZoneRules test2 = europeParis();
1104         ZoneRules test2b = europeParis();
1105         assertEquals(test1.equals(test2), false);
1106         assertEquals(test2.equals(test1), false);
1107 
1108         assertEquals(test1.equals(test1), true);
1109         assertEquals(test2.equals(test2), true);
1110         assertEquals(test2.equals(test2b), true);
1111 
1112         assertEquals(test1.hashCode() == test1.hashCode(), true);
1113         assertEquals(test2.hashCode() == test2.hashCode(), true);
1114         assertEquals(test2.hashCode() == test2b.hashCode(), true);
1115     }
1116 
1117     @Test
test_equals_null()1118     public void test_equals_null() {
1119         assertEquals(europeLondon().equals(null), false);
1120     }
1121 
1122     @Test
test_equals_notZoneRules()1123     public void test_equals_notZoneRules() {
1124         assertEquals(europeLondon().equals("Europe/London"), false);
1125     }
1126 
1127     @Test
test_toString()1128     public void test_toString() {
1129         assertEquals(europeLondon().toString().contains("ZoneRules"), true);
1130     }
1131 
1132     //-----------------------------------------------------------------------
1133     //-----------------------------------------------------------------------
1134     //-----------------------------------------------------------------------
createInstant(int year, int month, int day, ZoneOffset offset)1135     private Instant createInstant(int year, int month, int day, ZoneOffset offset) {
1136         return LocalDateTime.of(year, month, day, 0, 0).toInstant(offset);
1137     }
1138 
createInstant(int year, int month, int day, int hour, int min, ZoneOffset offset)1139     private Instant createInstant(int year, int month, int day, int hour, int min, ZoneOffset offset) {
1140         return LocalDateTime.of(year, month, day, hour, min).toInstant(offset);
1141     }
1142 
createInstant(int year, int month, int day, int hour, int min, int sec, int nano, ZoneOffset offset)1143     private Instant createInstant(int year, int month, int day, int hour, int min, int sec, int nano, ZoneOffset offset) {
1144         return LocalDateTime.of(year, month, day, hour, min, sec, nano).toInstant(offset);
1145     }
1146 
createZDT(int year, int month, int day, ZoneId zone)1147     private ZonedDateTime createZDT(int year, int month, int day, ZoneId zone) {
1148         return LocalDateTime.of(year, month, day, 0, 0).atZone(zone);
1149     }
1150 
createLDT(int year, int month, int day)1151     private LocalDateTime createLDT(int year, int month, int day) {
1152         return LocalDateTime.of(year, month, day, 0, 0);
1153     }
1154 
checkOffset(ZoneRules rules, LocalDateTime dateTime, ZoneOffset offset, int type)1155     private ZoneOffsetTransition checkOffset(ZoneRules rules, LocalDateTime dateTime, ZoneOffset offset, int type) {
1156         List<ZoneOffset> validOffsets = rules.getValidOffsets(dateTime);
1157         assertEquals(validOffsets.size(), type);
1158         assertEquals(rules.getOffset(dateTime), offset);
1159         if (type == 1) {
1160             assertEquals(validOffsets.get(0), offset);
1161             return null;
1162         } else {
1163             ZoneOffsetTransition zot = rules.getTransition(dateTime);
1164             assertNotNull(zot);
1165             assertEquals(zot.isOverlap(), type == 2);
1166             assertEquals(zot.isGap(), type == 0);
1167             assertEquals(zot.isValidOffset(offset), type == 2);
1168             return zot;
1169         }
1170     }
1171 
1172 }
1173