1   /*
2    *  Copyright 2001-2006 Stephen Colebourne
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  package org.joda.time;
17  
18  import java.io.ByteArrayInputStream;
19  import java.io.ByteArrayOutputStream;
20  import java.io.ObjectInputStream;
21  import java.io.ObjectOutputStream;
22  import java.io.PrintStream;
23  import java.lang.reflect.Modifier;
24  import java.security.AllPermission;
25  import java.security.CodeSource;
26  import java.security.Permission;
27  import java.security.PermissionCollection;
28  import java.security.Permissions;
29  import java.security.Policy;
30  import java.security.ProtectionDomain;
31  import java.util.HashSet;
32  import java.util.Locale;
33  import java.util.Set;
34  import java.util.TimeZone;
35  
36  import junit.framework.TestCase;
37  import junit.framework.TestSuite;
38  
39  import org.joda.time.tz.DefaultNameProvider;
40  import org.joda.time.tz.NameProvider;
41  import org.joda.time.tz.Provider;
42  import org.joda.time.tz.UTCProvider;
43  import org.joda.time.tz.ZoneInfoProvider;
44  
45  /***
46   * This class is a JUnit test for DateTimeZone.
47   *
48   * @author Stephen Colebourne
49   */
50  public class TestDateTimeZone extends TestCase {
51      private static final boolean OLD_JDK;
52      static {
53          String str = System.getProperty("java.version");
54          boolean old = true;
55          if (str.length() > 3 &&
56              str.charAt(0) == '1' &&
57              str.charAt(1) == '.' &&
58              (str.charAt(2) == '4' || str.charAt(2) == '5' || str.charAt(2) == '6')) {
59              old = false;
60          }
61          OLD_JDK = old;
62      }
63      
64      // Test in 2002/03 as time zones are more well known
65      // (before the late 90's they were all over the place)
66  
67      private static final DateTimeZone PARIS = DateTimeZone.forID("Europe/Paris");
68      private static final DateTimeZone LONDON = DateTimeZone.forID("Europe/London");
69      
70      long y2002days = 365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 + 
71                       366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 
72                       365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 +
73                       366 + 365;
74      long y2003days = 365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 + 
75                       366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 
76                       365 + 365 + 366 + 365 + 365 + 365 + 366 + 365 + 365 + 365 +
77                       366 + 365 + 365;
78      
79      // 2002-06-09
80      private long TEST_TIME_SUMMER =
81              (y2002days + 31L + 28L + 31L + 30L + 31L + 9L -1L) * DateTimeConstants.MILLIS_PER_DAY;
82              
83      // 2002-01-09
84      private long TEST_TIME_WINTER =
85              (y2002days + 9L -1L) * DateTimeConstants.MILLIS_PER_DAY;
86              
87  //    // 2002-04-05 Fri
88  //    private long TEST_TIME1 =
89  //            (y2002days + 31L + 28L + 31L + 5L -1L) * DateTimeConstants.MILLIS_PER_DAY
90  //            + 12L * DateTimeConstants.MILLIS_PER_HOUR
91  //            + 24L * DateTimeConstants.MILLIS_PER_MINUTE;
92  //        
93  //    // 2003-05-06 Tue
94  //    private long TEST_TIME2 =
95  //            (y2003days + 31L + 28L + 31L + 30L + 6L -1L) * DateTimeConstants.MILLIS_PER_DAY
96  //            + 14L * DateTimeConstants.MILLIS_PER_HOUR
97  //            + 28L * DateTimeConstants.MILLIS_PER_MINUTE;
98      
99      private static final Policy RESTRICT;
100     private static final Policy ALLOW;
101     static {
102         // don't call Policy.getPolicy()
103         RESTRICT = new Policy() {
104             public PermissionCollection getPermissions(CodeSource codesource) {
105                 Permissions p = new Permissions();
106                 p.add(new AllPermission());  // enable everything
107                 return p;
108             }
109             public void refresh() {
110             }
111             public boolean implies(ProtectionDomain domain, Permission permission) {
112                 if (permission instanceof JodaTimePermission) {
113                     return false;
114                 }
115                 return true;
116 //                return super.implies(domain, permission);
117             }
118         };
119         ALLOW = new Policy() {
120             public PermissionCollection getPermissions(CodeSource codesource) {
121                 Permissions p = new Permissions();
122                 p.add(new AllPermission());  // enable everything
123                 return p;
124             }
125             public void refresh() {
126             }
127         };
128     }
129     
130     private DateTimeZone zone;
131     private Locale locale;
132 
133     public static void main(String[] args) {
134         junit.textui.TestRunner.run(suite());
135     }
136 
137     public static TestSuite suite() {
138         return new TestSuite(TestDateTimeZone.class);
139     }
140 
141     public TestDateTimeZone(String name) {
142         super(name);
143     }
144 
145     protected void setUp() throws Exception {
146         locale = Locale.getDefault();
147         zone = DateTimeZone.getDefault();
148         Locale.setDefault(Locale.UK);
149     }
150 
151     protected void tearDown() throws Exception {
152         Locale.setDefault(locale);
153         DateTimeZone.setDefault(zone);
154     }
155 
156     //-----------------------------------------------------------------------
157     public void testDefault() {
158         assertNotNull(DateTimeZone.getDefault());
159         
160         DateTimeZone.setDefault(PARIS);
161         assertSame(PARIS, DateTimeZone.getDefault());
162         
163         try {
164             DateTimeZone.setDefault(null);
165             fail();
166         } catch (IllegalArgumentException ex) {}
167     }
168             
169     public void testDefaultSecurity() {
170         if (OLD_JDK) {
171             return;
172         }
173         try {
174             Policy.setPolicy(RESTRICT);
175             System.setSecurityManager(new SecurityManager());
176             DateTimeZone.setDefault(PARIS);
177             fail();
178         } catch (SecurityException ex) {
179             // ok
180         } finally {
181             System.setSecurityManager(null);
182             Policy.setPolicy(ALLOW);
183         }
184     }
185 
186     //-----------------------------------------------------------------------
187     public void testForID_String() {
188         assertEquals(DateTimeZone.getDefault(), DateTimeZone.forID((String) null));
189         
190         DateTimeZone zone = DateTimeZone.forID("Europe/London");
191         assertEquals("Europe/London", zone.getID());
192         
193         zone = DateTimeZone.forID("UTC");
194         assertSame(DateTimeZone.UTC, zone);
195         
196         zone = DateTimeZone.forID("+00:00");
197         assertSame(DateTimeZone.UTC, zone);
198         
199         zone = DateTimeZone.forID("+00");
200         assertSame(DateTimeZone.UTC, zone);
201         
202         zone = DateTimeZone.forID("+01:23");
203         assertEquals("+01:23", zone.getID());
204         assertEquals(DateTimeConstants.MILLIS_PER_HOUR + (23L * DateTimeConstants.MILLIS_PER_MINUTE),
205                 zone.getOffset(TEST_TIME_SUMMER));
206         
207         zone = DateTimeZone.forID("-02:00");
208         assertEquals("-02:00", zone.getID());
209         assertEquals((-2L * DateTimeConstants.MILLIS_PER_HOUR),
210                 zone.getOffset(TEST_TIME_SUMMER));
211         
212         zone = DateTimeZone.forID("-07:05:34.0");
213         assertEquals("-07:05:34", zone.getID());
214         assertEquals((-7L * DateTimeConstants.MILLIS_PER_HOUR) +
215                     (-5L * DateTimeConstants.MILLIS_PER_MINUTE) +
216                     (-34L * DateTimeConstants.MILLIS_PER_SECOND),
217                     zone.getOffset(TEST_TIME_SUMMER));
218         
219         try {
220             DateTimeZone.forID("SST");
221             fail();
222         } catch (IllegalArgumentException ex) {}
223         try {
224             DateTimeZone.forID("Europe/UK");
225             fail();
226         } catch (IllegalArgumentException ex) {}
227         try {
228             DateTimeZone.forID("+");
229             fail();
230         } catch (IllegalArgumentException ex) {}
231         try {
232             DateTimeZone.forID("+0");
233             fail();
234         } catch (IllegalArgumentException ex) {}
235     }
236 
237     //-----------------------------------------------------------------------
238     public void testForOffsetHours_int() {
239         assertEquals(DateTimeZone.UTC, DateTimeZone.forOffsetHours(0));
240         assertEquals(DateTimeZone.forID("+03:00"), DateTimeZone.forOffsetHours(3));
241         assertEquals(DateTimeZone.forID("-02:00"), DateTimeZone.forOffsetHours(-2));
242         try {
243             DateTimeZone.forOffsetHours(999999);
244             fail();
245         } catch (IllegalArgumentException ex) {}
246     }        
247 
248     //-----------------------------------------------------------------------
249     public void testForOffsetHoursMinutes_int_int() {
250         assertEquals(DateTimeZone.UTC, DateTimeZone.forOffsetHoursMinutes(0, 0));
251         assertEquals(DateTimeZone.forID("+03:15"), DateTimeZone.forOffsetHoursMinutes(3, 15));
252         assertEquals(DateTimeZone.forID("-02:00"), DateTimeZone.forOffsetHoursMinutes(-2, 0));
253         assertEquals(DateTimeZone.forID("-02:30"), DateTimeZone.forOffsetHoursMinutes(-2, 30));
254         try {
255             DateTimeZone.forOffsetHoursMinutes(2, 60);
256             fail();
257         } catch (IllegalArgumentException ex) {}
258         try {
259             DateTimeZone.forOffsetHoursMinutes(-2, 60);
260             fail();
261         } catch (IllegalArgumentException ex) {}
262         try {
263             DateTimeZone.forOffsetHoursMinutes(2, -1);
264             fail();
265         } catch (IllegalArgumentException ex) {}
266         try {
267             DateTimeZone.forOffsetHoursMinutes(-2, -1);
268             fail();
269         } catch (IllegalArgumentException ex) {}
270         try {
271             DateTimeZone.forOffsetHoursMinutes(999999, 0);
272             fail();
273         } catch (IllegalArgumentException ex) {}
274     }        
275 
276     //-----------------------------------------------------------------------
277     public void testForOffsetMillis_int() {
278         assertSame(DateTimeZone.UTC, DateTimeZone.forOffsetMillis(0));
279         assertEquals(DateTimeZone.forID("+03:00"), DateTimeZone.forOffsetMillis(3 * 60 * 60 * 1000));
280         assertEquals(DateTimeZone.forID("-02:00"), DateTimeZone.forOffsetMillis(-2 * 60 * 60 * 1000));
281         assertEquals(DateTimeZone.forID("+04:45:17.045"),
282                 DateTimeZone.forOffsetMillis(
283                         4 * 60 * 60 * 1000 + 45 * 60 * 1000 + 17 * 1000 + 45));
284     }        
285 
286     //-----------------------------------------------------------------------
287     public void testForTimeZone_TimeZone() {
288         assertEquals(DateTimeZone.getDefault(), DateTimeZone.forTimeZone((TimeZone) null));
289         
290         DateTimeZone zone = DateTimeZone.forTimeZone(TimeZone.getTimeZone("Europe/London"));
291         assertEquals("Europe/London", zone.getID());
292         assertSame(DateTimeZone.UTC, DateTimeZone.forTimeZone(TimeZone.getTimeZone("UTC")));
293         
294         zone = DateTimeZone.forTimeZone(TimeZone.getTimeZone("+00:00"));
295         assertSame(DateTimeZone.UTC, zone);
296         
297         zone = DateTimeZone.forTimeZone(TimeZone.getTimeZone("GMT+00:00"));
298         assertSame(DateTimeZone.UTC, zone);
299         
300         zone = DateTimeZone.forTimeZone(TimeZone.getTimeZone("GMT+00:00"));
301         assertSame(DateTimeZone.UTC, zone);
302         
303         zone = DateTimeZone.forTimeZone(TimeZone.getTimeZone("GMT+00"));
304         assertSame(DateTimeZone.UTC, zone);
305         
306         zone = DateTimeZone.forTimeZone(TimeZone.getTimeZone("GMT+01:23"));
307         assertEquals("+01:23", zone.getID());
308         assertEquals(DateTimeConstants.MILLIS_PER_HOUR + (23L * DateTimeConstants.MILLIS_PER_MINUTE),
309                 zone.getOffset(TEST_TIME_SUMMER));
310         
311         zone = DateTimeZone.forTimeZone(TimeZone.getTimeZone("GMT-02:00"));
312         assertEquals("-02:00", zone.getID());
313         assertEquals((-2L * DateTimeConstants.MILLIS_PER_HOUR), zone.getOffset(TEST_TIME_SUMMER));
314         
315         zone = DateTimeZone.forTimeZone(TimeZone.getTimeZone("EST"));
316         assertEquals("America/New_York", zone.getID());
317     }
318 
319     public void testTimeZoneConversion() {
320         TimeZone jdkTimeZone = TimeZone.getTimeZone("GMT-10");
321         assertEquals("GMT-10:00", jdkTimeZone.getID());
322         
323         DateTimeZone jodaTimeZone = DateTimeZone.forTimeZone(jdkTimeZone);
324         assertEquals("-10:00", jodaTimeZone.getID());
325         assertEquals(jdkTimeZone.getRawOffset(), jodaTimeZone.getOffset(0L));
326         
327         TimeZone convertedTimeZone = jodaTimeZone.toTimeZone();
328         assertEquals("GMT-10:00", jdkTimeZone.getID());
329         
330         assertEquals(jdkTimeZone.getID(), convertedTimeZone.getID());
331         assertEquals(jdkTimeZone.getRawOffset(), convertedTimeZone.getRawOffset());
332     }
333 
334     //-----------------------------------------------------------------------
335     public void testGetAvailableIDs() {
336         assertTrue(DateTimeZone.getAvailableIDs().contains("UTC"));
337     }
338 
339     //-----------------------------------------------------------------------
340     public void testProvider() {
341         try {
342             assertNotNull(DateTimeZone.getProvider());
343         
344             Provider provider = DateTimeZone.getProvider();
345             DateTimeZone.setProvider(null);
346             assertEquals(provider.getClass(), DateTimeZone.getProvider().getClass());
347         
348             try {
349                 DateTimeZone.setProvider(new MockNullIDSProvider());
350                 fail();
351             } catch (IllegalArgumentException ex) {}
352             try {
353                 DateTimeZone.setProvider(new MockEmptyIDSProvider());
354                 fail();
355             } catch (IllegalArgumentException ex) {}
356             try {
357                 DateTimeZone.setProvider(new MockNoUTCProvider());
358                 fail();
359             } catch (IllegalArgumentException ex) {}
360             try {
361                 DateTimeZone.setProvider(new MockBadUTCProvider());
362                 fail();
363             } catch (IllegalArgumentException ex) {}
364         
365             Provider prov = new MockOKProvider();
366             DateTimeZone.setProvider(prov);
367             assertSame(prov, DateTimeZone.getProvider());
368             assertEquals(2, DateTimeZone.getAvailableIDs().size());
369             assertTrue(DateTimeZone.getAvailableIDs().contains("UTC"));
370             assertTrue(DateTimeZone.getAvailableIDs().contains("Europe/London"));
371         } finally {
372             DateTimeZone.setProvider(null);
373             assertEquals(ZoneInfoProvider.class, DateTimeZone.getProvider().getClass());
374         }
375         
376         try {
377             System.setProperty("org.joda.time.DateTimeZone.Provider", "org.joda.time.tz.UTCProvider");
378             DateTimeZone.setProvider(null);
379             assertEquals(UTCProvider.class, DateTimeZone.getProvider().getClass());
380         } finally {
381             System.getProperties().remove("org.joda.time.DateTimeZone.Provider");
382             DateTimeZone.setProvider(null);
383             assertEquals(ZoneInfoProvider.class, DateTimeZone.getProvider().getClass());
384         }
385         
386         PrintStream syserr = System.err;
387         try {
388             System.setProperty("org.joda.time.DateTimeZone.Provider", "xxx");
389             ByteArrayOutputStream baos = new ByteArrayOutputStream();
390             System.setErr(new PrintStream(baos));
391             
392             DateTimeZone.setProvider(null);
393             
394             assertEquals(ZoneInfoProvider.class, DateTimeZone.getProvider().getClass());
395             String str = new String(baos.toByteArray());
396             assertTrue(str.indexOf("java.lang.ClassNotFoundException") >= 0);
397         } finally {
398             System.setErr(syserr);
399             System.getProperties().remove("org.joda.time.DateTimeZone.Provider");
400             DateTimeZone.setProvider(null);
401             assertEquals(ZoneInfoProvider.class, DateTimeZone.getProvider().getClass());
402         }
403     }
404     
405     public void testProviderSecurity() {
406         if (OLD_JDK) {
407             return;
408         }
409         try {
410             Policy.setPolicy(RESTRICT);
411             System.setSecurityManager(new SecurityManager());
412             DateTimeZone.setProvider(new MockOKProvider());
413             fail();
414         } catch (SecurityException ex) {
415             // ok
416         } finally {
417             System.setSecurityManager(null);
418             Policy.setPolicy(ALLOW);
419         }
420     }
421 
422     static class MockNullIDSProvider implements Provider {
423         public Set getAvailableIDs() {
424             return null;
425         }
426         public DateTimeZone getZone(String id) {
427             return null;
428         }
429     }
430     static class MockEmptyIDSProvider implements Provider {
431         public Set getAvailableIDs() {
432             return new HashSet();
433         }
434         public DateTimeZone getZone(String id) {
435             return null;
436         }
437     }
438     static class MockNoUTCProvider implements Provider {
439         public Set getAvailableIDs() {
440             Set set = new HashSet();
441             set.add("Europe/London");
442             return set;
443         }
444         public DateTimeZone getZone(String id) {
445             return null;
446         }
447     }
448     static class MockBadUTCProvider implements Provider {
449         public Set getAvailableIDs() {
450             Set set = new HashSet();
451             set.add("UTC");
452             set.add("Europe/London");
453             return set;
454         }
455         public DateTimeZone getZone(String id) {
456             return null;
457         }
458     }
459     static class MockOKProvider implements Provider {
460         public Set getAvailableIDs() {
461             Set set = new HashSet();
462             set.add("UTC");
463             set.add("Europe/London");
464             return set;
465         }
466         public DateTimeZone getZone(String id) {
467             return DateTimeZone.UTC;
468         }
469     }
470 
471     //-----------------------------------------------------------------------
472     public void testNameProvider() {
473         try {
474             assertNotNull(DateTimeZone.getNameProvider());
475         
476             NameProvider provider = DateTimeZone.getNameProvider();
477             DateTimeZone.setNameProvider(null);
478             assertEquals(provider.getClass(), DateTimeZone.getNameProvider().getClass());
479         
480             provider = new MockOKButNullNameProvider();
481             DateTimeZone.setNameProvider(provider);
482             assertSame(provider, DateTimeZone.getNameProvider());
483             
484             assertEquals("+00:00", DateTimeZone.UTC.getShortName(TEST_TIME_SUMMER));
485             assertEquals("+00:00", DateTimeZone.UTC.getName(TEST_TIME_SUMMER));
486         } finally {
487             DateTimeZone.setNameProvider(null);
488         }
489         
490         try {
491             System.setProperty("org.joda.time.DateTimeZone.NameProvider", "org.joda.time.tz.DefaultNameProvider");
492             DateTimeZone.setNameProvider(null);
493             assertEquals(DefaultNameProvider.class, DateTimeZone.getNameProvider().getClass());
494         } finally {
495             System.getProperties().remove("org.joda.time.DateTimeZone.NameProvider");
496             DateTimeZone.setNameProvider(null);
497             assertEquals(DefaultNameProvider.class, DateTimeZone.getNameProvider().getClass());
498         }
499         
500         PrintStream syserr = System.err;
501         try {
502             System.setProperty("org.joda.time.DateTimeZone.NameProvider", "xxx");
503             ByteArrayOutputStream baos = new ByteArrayOutputStream();
504             System.setErr(new PrintStream(baos));
505             
506             DateTimeZone.setNameProvider(null);
507             
508             assertEquals(DefaultNameProvider.class, DateTimeZone.getNameProvider().getClass());
509             String str = new String(baos.toByteArray());
510             assertTrue(str.indexOf("java.lang.ClassNotFoundException") >= 0);
511         } finally {
512             System.setErr(syserr);
513             System.getProperties().remove("org.joda.time.DateTimeZone.NameProvider");
514             DateTimeZone.setNameProvider(null);
515             assertEquals(DefaultNameProvider.class, DateTimeZone.getNameProvider().getClass());
516         }
517     }        
518     
519     public void testNameProviderSecurity() {
520         if (OLD_JDK) {
521             return;
522         }
523         try {
524             Policy.setPolicy(RESTRICT);
525             System.setSecurityManager(new SecurityManager());
526             DateTimeZone.setNameProvider(new MockOKButNullNameProvider());
527             fail();
528         } catch (SecurityException ex) {
529             // ok
530         } finally {
531             System.setSecurityManager(null);
532             Policy.setPolicy(ALLOW);
533         }
534     }
535 
536     static class MockOKButNullNameProvider implements NameProvider {
537         public String getShortName(Locale locale, String id, String nameKey) {
538             return null;
539         }
540         public String getName(Locale locale, String id, String nameKey) {
541             return null;
542         }
543     }
544 
545     //-----------------------------------------------------------------------
546     public void testConstructor() {
547         assertEquals(1, DateTimeZone.class.getDeclaredConstructors().length);
548         assertTrue(Modifier.isProtected(DateTimeZone.class.getDeclaredConstructors()[0].getModifiers()));
549         try {
550             new DateTimeZone(null) {
551                 public String getNameKey(long instant) {
552                     return null;
553                 }
554                 public int getOffset(long instant) {
555                     return 0;
556                 }
557                 public int getStandardOffset(long instant) {
558                     return 0;
559                 }
560                 public boolean isFixed() {
561                     return false;
562                 }
563                 public long nextTransition(long instant) {
564                     return 0;
565                 }
566                 public long previousTransition(long instant) {
567                     return 0;
568                 }
569                 public boolean equals(Object object) {
570                     return false;
571                 }
572             };
573         } catch (IllegalArgumentException ex) {}
574     }
575 
576     //-----------------------------------------------------------------------
577     public void testGetID() {
578         DateTimeZone zone = DateTimeZone.forID("Europe/Paris");
579         assertEquals("Europe/Paris", zone.getID());
580     }
581 
582     public void testGetNameKey() {
583         DateTimeZone zone = DateTimeZone.forID("Europe/London");
584         assertEquals("BST", zone.getNameKey(TEST_TIME_SUMMER));
585         assertEquals("GMT", zone.getNameKey(TEST_TIME_WINTER));
586     }
587 
588     public void testGetShortName() {
589         DateTimeZone zone = DateTimeZone.forID("Europe/London");
590         assertEquals("BST", zone.getShortName(TEST_TIME_SUMMER));
591         assertEquals("GMT", zone.getShortName(TEST_TIME_WINTER));
592         assertEquals("BST", zone.getShortName(TEST_TIME_SUMMER, Locale.ENGLISH));
593     }
594             
595     public void testGetShortNameProviderName() {
596         assertEquals(null, DateTimeZone.getNameProvider().getShortName(null, "Europe/London", "BST"));
597         assertEquals(null, DateTimeZone.getNameProvider().getShortName(Locale.ENGLISH, null, "BST"));
598         assertEquals(null, DateTimeZone.getNameProvider().getShortName(Locale.ENGLISH, "Europe/London", null));
599         assertEquals(null, DateTimeZone.getNameProvider().getShortName(null, null, null));
600     }
601     
602     public void testGetShortNameNullKey() {
603         DateTimeZone zone = new MockDateTimeZone("Europe/London");
604         assertEquals("Europe/London", zone.getShortName(TEST_TIME_SUMMER, Locale.ENGLISH));
605     }
606     
607     public void testGetName() {
608         DateTimeZone zone = DateTimeZone.forID("Europe/London");
609         assertEquals("British Summer Time", zone.getName(TEST_TIME_SUMMER));
610         assertEquals("Greenwich Mean Time", zone.getName(TEST_TIME_WINTER));
611         assertEquals("British Summer Time", zone.getName(TEST_TIME_SUMMER, Locale.ENGLISH));
612         
613     }
614     
615     public void testGetNameProviderName() {
616         assertEquals(null, DateTimeZone.getNameProvider().getName(null, "Europe/London", "BST"));
617         assertEquals(null, DateTimeZone.getNameProvider().getName(Locale.ENGLISH, null, "BST"));
618         assertEquals(null, DateTimeZone.getNameProvider().getName(Locale.ENGLISH, "Europe/London", null));
619         assertEquals(null, DateTimeZone.getNameProvider().getName(null, null, null));
620     }
621     
622     public void testGetNameNullKey() {
623         DateTimeZone zone = new MockDateTimeZone("Europe/London");
624         assertEquals("Europe/London", zone.getName(TEST_TIME_SUMMER, Locale.ENGLISH));
625     }
626     
627     static class MockDateTimeZone extends DateTimeZone {
628         public MockDateTimeZone(String id) {
629             super(id);
630         }
631         public String getNameKey(long instant) {
632             return null;  // null
633         }
634         public int getOffset(long instant) {
635             return 0;
636         }
637         public int getStandardOffset(long instant) {
638             return 0;
639         }
640         public boolean isFixed() {
641             return false;
642         }
643         public long nextTransition(long instant) {
644             return 0;
645         }
646         public long previousTransition(long instant) {
647             return 0;
648         }
649         public boolean equals(Object object) {
650             return false;
651         }
652     }
653 
654     //-----------------------------------------------------------------------
655     public void testGetOffset_long() {
656         DateTimeZone zone = DateTimeZone.forID("Europe/Paris");
657         assertEquals(2L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffset(TEST_TIME_SUMMER));
658         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffset(TEST_TIME_WINTER));
659         
660         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getStandardOffset(TEST_TIME_SUMMER));
661         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getStandardOffset(TEST_TIME_WINTER));
662         
663         assertEquals(2L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffsetFromLocal(TEST_TIME_SUMMER));
664         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffsetFromLocal(TEST_TIME_WINTER));
665         
666         assertEquals(false, zone.isStandardOffset(TEST_TIME_SUMMER));
667         assertEquals(true, zone.isStandardOffset(TEST_TIME_WINTER));
668     }
669 
670     public void testGetOffset_RI() {
671         DateTimeZone zone = DateTimeZone.forID("Europe/Paris");
672         assertEquals(2L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffset(new Instant(TEST_TIME_SUMMER)));
673         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffset(new Instant(TEST_TIME_WINTER)));
674         
675         assertEquals(zone.getOffset(DateTimeUtils.currentTimeMillis()), zone.getOffset(null));
676     }
677 
678     public void testGetOffsetFixed() {
679         DateTimeZone zone = DateTimeZone.forID("+01:00");
680         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffset(TEST_TIME_SUMMER));
681         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffset(TEST_TIME_WINTER));
682         
683         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getStandardOffset(TEST_TIME_SUMMER));
684         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getStandardOffset(TEST_TIME_WINTER));
685         
686         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffsetFromLocal(TEST_TIME_SUMMER));
687         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffsetFromLocal(TEST_TIME_WINTER));
688         
689         assertEquals(true, zone.isStandardOffset(TEST_TIME_SUMMER));
690         assertEquals(true, zone.isStandardOffset(TEST_TIME_WINTER));
691     }
692 
693     public void testGetOffsetFixed_RI() {
694         DateTimeZone zone = DateTimeZone.forID("+01:00");
695         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffset(new Instant(TEST_TIME_SUMMER)));
696         assertEquals(1L * DateTimeConstants.MILLIS_PER_HOUR, zone.getOffset(new Instant(TEST_TIME_WINTER)));
697         
698         assertEquals(zone.getOffset(DateTimeUtils.currentTimeMillis()), zone.getOffset(null));
699     }
700 
701     //-----------------------------------------------------------------------
702     public void testGetMillisKeepLocal() {
703         long millisLondon = TEST_TIME_SUMMER;
704         long millisParis = TEST_TIME_SUMMER - 1L * DateTimeConstants.MILLIS_PER_HOUR;
705         
706         assertEquals(millisLondon, LONDON.getMillisKeepLocal(LONDON, millisLondon));
707         assertEquals(millisParis, LONDON.getMillisKeepLocal(LONDON, millisParis));
708         assertEquals(millisLondon, PARIS.getMillisKeepLocal(PARIS, millisLondon));
709         assertEquals(millisParis, PARIS.getMillisKeepLocal(PARIS, millisParis));
710         
711         assertEquals(millisParis, LONDON.getMillisKeepLocal(PARIS, millisLondon));
712         assertEquals(millisLondon, PARIS.getMillisKeepLocal(LONDON, millisParis));
713         
714         DateTimeZone zone = DateTimeZone.getDefault();
715         try {
716             DateTimeZone.setDefault(LONDON);
717             assertEquals(millisLondon, PARIS.getMillisKeepLocal(null, millisParis));
718         } finally {
719             DateTimeZone.setDefault(zone);
720         }
721     }
722 
723     //-----------------------------------------------------------------------
724     public void testIsFixed() {
725         DateTimeZone zone = DateTimeZone.forID("Europe/Paris");
726         assertEquals(false, zone.isFixed());
727         assertEquals(true, DateTimeZone.UTC.isFixed());
728     }
729 
730     //-----------------------------------------------------------------------
731     public void testTransitionFixed() {
732         DateTimeZone zone = DateTimeZone.forID("+01:00");
733         assertEquals(TEST_TIME_SUMMER, zone.nextTransition(TEST_TIME_SUMMER));
734         assertEquals(TEST_TIME_WINTER, zone.nextTransition(TEST_TIME_WINTER));
735         assertEquals(TEST_TIME_SUMMER, zone.previousTransition(TEST_TIME_SUMMER));
736         assertEquals(TEST_TIME_WINTER, zone.previousTransition(TEST_TIME_WINTER));
737     }
738 
739 //    //-----------------------------------------------------------------------
740 //    public void testIsLocalDateTimeOverlap_Berlin() {
741 //        DateTimeZone zone = DateTimeZone.forID("Europe/Berlin");
742 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 10, 28, 1, 0)));
743 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 10, 28, 1, 59, 59, 99)));
744 //        assertEquals(true, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 10, 28, 2, 0)));
745 //        assertEquals(true, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 10, 28, 2, 30)));
746 //        assertEquals(true, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 10, 28, 2, 59, 59, 99)));
747 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 10, 28, 3, 0)));
748 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 10, 28, 4, 0)));
749 //        
750 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 3, 25, 1, 30)));  // before gap
751 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 3, 25, 2, 30)));  // gap
752 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 3, 25, 3, 30)));  // after gap
753 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 12, 24, 12, 34)));
754 //    }
755 //
756 //    //-----------------------------------------------------------------------
757 //    public void testIsLocalDateTimeOverlap_NewYork() {
758 //        DateTimeZone zone = DateTimeZone.forID("America/New_York");
759 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 11, 4, 0, 0)));
760 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 11, 4, 0, 59, 59, 99)));
761 //        assertEquals(true, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 11, 4, 1, 0)));
762 //        assertEquals(true, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 11, 4, 1, 30)));
763 //        assertEquals(true, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 11, 4, 1, 59, 59, 99)));
764 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 11, 4, 2, 0)));
765 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 11, 4, 3, 0)));
766 //        
767 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 3, 11, 1, 30)));  // before gap
768 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 3, 11, 2, 30)));  // gap
769 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 3, 11, 3, 30)));  // after gap
770 //        assertEquals(false, zone.isLocalDateTimeOverlap(new LocalDateTime(2007, 12, 24, 12, 34)));
771 //    }
772 
773     //-----------------------------------------------------------------------
774     public void testIsLocalDateTimeGap_Berlin() {
775         DateTimeZone zone = DateTimeZone.forID("Europe/Berlin");
776         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 25, 1, 0)));
777         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 25, 1, 59, 59, 99)));
778         assertEquals(true, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 25, 2, 0)));
779         assertEquals(true, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 25, 2, 30)));
780         assertEquals(true, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 25, 2, 59, 59, 99)));
781         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 25, 3, 0)));
782         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 25, 4, 0)));
783         
784         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 10, 28, 1, 30)));  // before overlap
785         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 10, 28, 2, 30)));  // overlap
786         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 10, 28, 3, 30)));  // after overlap
787         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 12, 24, 12, 34)));
788     }
789 
790     //-----------------------------------------------------------------------
791     public void testIsLocalDateTimeGap_NewYork() {
792         DateTimeZone zone = DateTimeZone.forID("America/New_York");
793         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 11, 1, 0)));
794         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 11, 1, 59, 59, 99)));
795         assertEquals(true, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 11, 2, 0)));
796         assertEquals(true, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 11, 2, 30)));
797         assertEquals(true, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 11, 2, 59, 59, 99)));
798         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 11, 3, 0)));
799         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 3, 11, 4, 0)));
800         
801         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 11, 4, 0, 30)));  // before overlap
802         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 11, 4, 1, 30)));  // overlap
803         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 11, 4, 2, 30)));  // after overlap
804         assertEquals(false, zone.isLocalDateTimeGap(new LocalDateTime(2007, 12, 24, 12, 34)));
805     }
806 
807     //-----------------------------------------------------------------------
808     public void testToTimeZone() {
809         DateTimeZone zone = DateTimeZone.forID("Europe/Paris");
810         TimeZone tz = zone.toTimeZone();
811         assertEquals("Europe/Paris", tz.getID());
812     }
813 
814     //-----------------------------------------------------------------------
815     public void testEqualsHashCode() {
816         DateTimeZone zone1 = DateTimeZone.forID("Europe/Paris");
817         DateTimeZone zone2 = DateTimeZone.forID("Europe/Paris");
818         assertEquals(true, zone1.equals(zone1));
819         assertEquals(true, zone1.equals(zone2));
820         assertEquals(true, zone2.equals(zone1));
821         assertEquals(true, zone2.equals(zone2));
822         assertEquals(true, zone1.hashCode() == zone2.hashCode());
823         
824         DateTimeZone zone3 = DateTimeZone.forID("Europe/London");
825         assertEquals(true, zone3.equals(zone3));
826         assertEquals(false, zone1.equals(zone3));
827         assertEquals(false, zone2.equals(zone3));
828         assertEquals(false, zone3.equals(zone1));
829         assertEquals(false, zone3.equals(zone2));
830         assertEquals(false, zone1.hashCode() == zone3.hashCode());
831         assertEquals(true, zone3.hashCode() == zone3.hashCode());
832         
833         DateTimeZone zone4 = DateTimeZone.forID("+01:00");
834         assertEquals(true, zone4.equals(zone4));
835         assertEquals(false, zone1.equals(zone4));
836         assertEquals(false, zone2.equals(zone4));
837         assertEquals(false, zone3.equals(zone4));
838         assertEquals(false, zone4.equals(zone1));
839         assertEquals(false, zone4.equals(zone2));
840         assertEquals(false, zone4.equals(zone3));
841         assertEquals(false, zone1.hashCode() == zone4.hashCode());
842         assertEquals(true, zone4.hashCode() == zone4.hashCode());
843         
844         DateTimeZone zone5 = DateTimeZone.forID("+02:00");
845         assertEquals(true, zone5.equals(zone5));
846         assertEquals(false, zone1.equals(zone5));
847         assertEquals(false, zone2.equals(zone5));
848         assertEquals(false, zone3.equals(zone5));
849         assertEquals(false, zone4.equals(zone5));
850         assertEquals(false, zone5.equals(zone1));
851         assertEquals(false, zone5.equals(zone2));
852         assertEquals(false, zone5.equals(zone3));
853         assertEquals(false, zone5.equals(zone4));
854         assertEquals(false, zone1.hashCode() == zone5.hashCode());
855         assertEquals(true, zone5.hashCode() == zone5.hashCode());
856     }
857 
858     //-----------------------------------------------------------------------
859     public void testToString() {
860         DateTimeZone zone = DateTimeZone.forID("Europe/Paris");
861         assertEquals("Europe/Paris", zone.toString());
862         assertEquals("UTC", DateTimeZone.UTC.toString());
863     }
864 
865     //-----------------------------------------------------------------------
866     public void testSerialization1() throws Exception {
867         DateTimeZone zone = DateTimeZone.forID("Europe/Paris");
868         
869         ByteArrayOutputStream baos = new ByteArrayOutputStream();
870         ObjectOutputStream oos = new ObjectOutputStream(baos);
871         oos.writeObject(zone);
872         byte[] bytes = baos.toByteArray();
873         oos.close();
874         
875         ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
876         ObjectInputStream ois = new ObjectInputStream(bais);
877         DateTimeZone result = (DateTimeZone) ois.readObject();
878         ois.close();
879         
880         assertSame(zone, result);
881     }
882 
883     //-----------------------------------------------------------------------
884     public void testSerialization2() throws Exception {
885         DateTimeZone zone = DateTimeZone.forID("+01:00");
886         
887         ByteArrayOutputStream baos = new ByteArrayOutputStream();
888         ObjectOutputStream oos = new ObjectOutputStream(baos);
889         oos.writeObject(zone);
890         byte[] bytes = baos.toByteArray();
891         oos.close();
892         
893         ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
894         ObjectInputStream ois = new ObjectInputStream(bais);
895         DateTimeZone result = (DateTimeZone) ois.readObject();
896         ois.close();
897         
898         assertSame(zone, result);
899     }
900 
901     public void testCommentParse() throws Exception {
902         // A bug in ZoneInfoCompiler's handling of comments broke Europe/Athens
903         // after 1980. This test is included to make sure it doesn't break again.
904 
905         DateTimeZone zone = DateTimeZone.forID("Europe/Athens");
906         DateTime dt = new DateTime(2005, 5, 5, 20, 10, 15, 0, zone);
907         assertEquals(1115313015000L, dt.getMillis());
908     }
909 
910     public void testPatchedNameKeysLondon() throws Exception {
911         // the tz database does not have unique name keys [1716305]
912         DateTimeZone zone = DateTimeZone.forID("Europe/London");
913         
914         DateTime now = new DateTime(2007, 1, 1, 0, 0, 0, 0);
915         String str1 = zone.getName(now.getMillis());
916         String str2 = zone.getName(now.plusMonths(6).getMillis());
917         assertEquals(false, str1.equals(str2));
918     }
919 
920     public void testPatchedNameKeysSydney() throws Exception {
921         // the tz database does not have unique name keys [1716305]
922         DateTimeZone zone = DateTimeZone.forID("Australia/Sydney");
923         
924         DateTime now = new DateTime(2007, 1, 1, 0, 0, 0, 0);
925         String str1 = zone.getName(now.getMillis());
926         String str2 = zone.getName(now.plusMonths(6).getMillis());
927         assertEquals(false, str1.equals(str2));
928     }
929 
930     public void testPatchedNameKeysSydneyHistoric() throws Exception {
931         // the tz database does not have unique name keys [1716305]
932         DateTimeZone zone = DateTimeZone.forID("Australia/Sydney");
933         
934         DateTime now = new DateTime(1996, 1, 1, 0, 0, 0, 0);
935         String str1 = zone.getName(now.getMillis());
936         String str2 = zone.getName(now.plusMonths(6).getMillis());
937         assertEquals(false, str1.equals(str2));
938     }
939 
940     public void testPatchedNameKeysGazaHistoric() throws Exception {
941         // the tz database does not have unique name keys [1716305]
942         DateTimeZone zone = DateTimeZone.forID("Africa/Johannesburg");
943         
944         DateTime now = new DateTime(1943, 1, 1, 0, 0, 0, 0);
945         String str1 = zone.getName(now.getMillis());
946         String str2 = zone.getName(now.plusMonths(6).getMillis());
947         assertEquals(false, str1.equals(str2));
948     }
949 
950 }