View Javadoc

1   /*
2    *  Copyright 2001-2005 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.tz;
17  
18  import java.io.ByteArrayInputStream;
19  import java.io.ByteArrayOutputStream;
20  import java.io.IOException;
21  
22  import junit.framework.TestCase;
23  import junit.framework.TestSuite;
24  
25  import org.joda.time.DateTime;
26  import org.joda.time.DateTimeZone;
27  import org.joda.time.format.DateTimeFormatter;
28  import org.joda.time.format.DateTimeFormatterBuilder;
29  
30  /**
31   * Test cases for DateTimeZoneBuilder.
32   *
33   * @author Brian S O'Neill
34   */
35  public class TestBuilder extends TestCase {
36      public static void main(String[] args) {
37          junit.textui.TestRunner.run(suite());
38      }
39  
40      public static TestSuite suite() {
41          return new TestSuite(TestBuilder.class);
42      }
43  
44      static final DateTimeFormatter OFFSET_FORMATTER = new DateTimeFormatterBuilder()
45          .appendTimeZoneOffset(null, true, 2, 4)
46          .toFormatter();
47  
48      // Each row is {transition, nameKey, standardOffset, offset}
49      static final String[][] AMERICA_LOS_ANGELES_DATA = {
50          {null,                            "LMT", "-07:52:58", "-07:52:58"},
51          {"1883-11-18T19:52:58.000Z",      "PST", "-08:00", "-08:00"},
52          {"1918-03-31T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
53          {"1918-10-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
54          {"1919-03-30T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
55          {"1919-10-26T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
56          {"1942-02-09T02:00:00.000-08:00", "PWT", "-08:00", "-07:00"},
57          {"1945-08-14T23:00:00.000Z",      "PPT", "-08:00", "-07:00"},
58          {"1945-09-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
59          {"1948-03-14T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
60          {"1949-01-01T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
61          {"1950-04-30T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
62          {"1950-09-24T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
63          {"1951-04-29T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
64          {"1951-09-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
65          {"1952-04-27T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
66          {"1952-09-28T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
67          {"1953-04-26T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
68          {"1953-09-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
69          {"1954-04-25T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
70          {"1954-09-26T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
71          {"1955-04-24T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
72          {"1955-09-25T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
73          {"1956-04-29T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
74          {"1956-09-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
75          {"1957-04-28T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
76          {"1957-09-29T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
77          {"1958-04-27T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
78          {"1958-09-28T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
79          {"1959-04-26T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
80          {"1959-09-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
81          {"1960-04-24T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
82          {"1960-09-25T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
83          {"1961-04-30T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
84          {"1961-09-24T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
85          {"1962-04-29T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
86          {"1962-10-28T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
87          {"1963-04-28T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
88          {"1963-10-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
89          {"1964-04-26T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
90          {"1964-10-25T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
91          {"1965-04-25T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
92          {"1965-10-31T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
93          {"1966-04-24T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
94          {"1966-10-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
95          {"1967-04-30T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
96          {"1967-10-29T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
97          {"1968-04-28T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
98          {"1968-10-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
99          {"1969-04-27T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
100         {"1969-10-26T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
101         {"1970-04-26T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
102         {"1970-10-25T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
103         {"1971-04-25T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
104         {"1971-10-31T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
105         {"1972-04-30T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
106         {"1972-10-29T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
107         {"1973-04-29T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
108         {"1973-10-28T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
109         {"1974-01-06T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
110         {"1974-10-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
111         {"1975-02-23T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
112         {"1975-10-26T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
113         {"1976-04-25T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
114         {"1976-10-31T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
115         {"1977-04-24T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
116         {"1977-10-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
117         {"1978-04-30T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
118         {"1978-10-29T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
119         {"1979-04-29T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
120         {"1979-10-28T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
121         {"1980-04-27T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
122         {"1980-10-26T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
123         {"1981-04-26T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
124         {"1981-10-25T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
125         {"1982-04-25T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
126         {"1982-10-31T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
127         {"1983-04-24T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
128         {"1983-10-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
129         {"1984-04-29T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
130         {"1984-10-28T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
131         {"1985-04-28T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
132         {"1985-10-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
133         {"1986-04-27T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
134         {"1986-10-26T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
135         {"1987-04-05T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
136         {"1987-10-25T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
137         {"1988-04-03T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
138         {"1988-10-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
139         {"1989-04-02T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
140         {"1989-10-29T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
141         {"1990-04-01T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
142         {"1990-10-28T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
143         {"1991-04-07T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
144         {"1991-10-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
145         {"1992-04-05T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
146         {"1992-10-25T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
147         {"1993-04-04T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
148         {"1993-10-31T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
149         {"1994-04-03T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
150         {"1994-10-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
151         {"1995-04-02T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
152         {"1995-10-29T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
153         {"1996-04-07T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
154         {"1996-10-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
155         {"1997-04-06T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
156         {"1997-10-26T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
157         {"1998-04-05T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
158         {"1998-10-25T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
159         {"1999-04-04T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
160         {"1999-10-31T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
161         {"2000-04-02T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
162         {"2000-10-29T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
163     };
164 
165     static DateTimeZoneBuilder buildAmericaLosAngelesBuilder() {
166         return new DateTimeZoneBuilder()
167             .addCutover(-2147483648, 'w', 1, 1, 0, false, 0)
168             .setStandardOffset(-28378000)
169             .setFixedSavings("LMT", 0)
170             .addCutover(1883, 'w', 11, 18, 0, false, 43200000)
171             .setStandardOffset(-28800000)
172             .addRecurringSavings("PDT", 3600000, 1918, 1919, 'w',  3, -1, 7, false, 7200000)
173             .addRecurringSavings("PST",       0, 1918, 1919, 'w', 10, -1, 7, false, 7200000)
174             .addRecurringSavings("PWT", 3600000, 1942, 1942, 'w',  2,  9, 0, false, 7200000)
175             .addRecurringSavings("PPT", 3600000, 1945, 1945, 'u',  8, 14, 0, false, 82800000)
176             .addRecurringSavings("PST",       0, 1945, 1945, 'w',  9, 30, 0, false, 7200000)
177             .addRecurringSavings("PDT", 3600000, 1948, 1948, 'w',  3, 14, 0, false, 7200000)
178             .addRecurringSavings("PST",       0, 1949, 1949, 'w',  1,  1, 0, false, 7200000)
179             .addRecurringSavings("PDT", 3600000, 1950, 1966, 'w',  4, -1, 7, false, 7200000)
180             .addRecurringSavings("PST",       0, 1950, 1961, 'w',  9, -1, 7, false, 7200000)
181             .addRecurringSavings("PST",       0, 1962, 1966, 'w', 10, -1, 7, false, 7200000)
182             .addRecurringSavings("PST",       0, 1967, 2147483647, 'w', 10, -1, 7, false, 7200000)
183             .addRecurringSavings("PDT", 3600000, 1967, 1973, 'w', 4, -1,  7, false, 7200000)
184             .addRecurringSavings("PDT", 3600000, 1974, 1974, 'w', 1,  6,  0, false, 7200000)
185             .addRecurringSavings("PDT", 3600000, 1975, 1975, 'w', 2, 23,  0, false, 7200000)
186             .addRecurringSavings("PDT", 3600000, 1976, 1986, 'w', 4, -1,  7, false, 7200000)
187             .addRecurringSavings("PDT", 3600000, 1987, 2147483647, 'w', 4, 1, 7, true, 7200000);
188     }
189 
190     static DateTimeZone buildAmericaLosAngeles() {
191         return buildAmericaLosAngelesBuilder().toDateTimeZone("America/Los_Angeles", true);
192     }
193 
194     private DateTimeZone originalDateTimeZone = null;
195 
196     public TestBuilder(String name) {
197         super(name);
198     }
199 
200     protected void setUp() throws Exception {
201         originalDateTimeZone = DateTimeZone.getDefault();
202         DateTimeZone.setDefault(DateTimeZone.UTC);
203     }
204 
205     protected void tearDown() throws Exception {
206         DateTimeZone.setDefault(originalDateTimeZone);
207     }
208 
209     public void testID() {
210         DateTimeZone tz = buildAmericaLosAngeles();
211         assertEquals("America/Los_Angeles", tz.getID());
212         assertEquals(false, tz.isFixed());
213     }
214 
215     public void testForwardTransitions() {
216         DateTimeZone tz = buildAmericaLosAngeles();
217         testForwardTransitions(tz, AMERICA_LOS_ANGELES_DATA);
218     }
219 
220     static void testForwardTransitions(DateTimeZone tz, String[][] data) {
221         long instant = Long.MIN_VALUE;
222         for (int i=0; i<data.length; i++) {
223             String[] row = data[i];
224             long expectedInstant = instant;
225             if (row[0] != null) {
226                 instant = tz.nextTransition(instant);
227                 expectedInstant = new DateTime(row[0]).getMillis();
228             }
229 
230             String expectedKey = row[1];
231             int expectedStandardOffset = -(int) OFFSET_FORMATTER.parseMillis(row[2]);
232             int expectedOffset = -(int) OFFSET_FORMATTER.parseMillis(row[3]);
233 
234             assertEquals(expectedInstant, instant);
235             assertEquals(expectedKey, tz.getNameKey(instant));
236             assertEquals(expectedStandardOffset, tz.getStandardOffset(instant));
237             assertEquals(expectedOffset, tz.getOffset(instant));
238 
239             // Sample a few instants between transitions.
240             if (i < data.length - 1) {
241                 long nextInstant = new DateTime(data[i + 1][0]).getMillis();
242                 long span = (nextInstant - instant) / 10;
243                 for (int j=1; j<10; j++) {
244                     long between = instant + j * span;
245                     assertEquals(expectedKey, tz.getNameKey(between));
246                     assertEquals(expectedStandardOffset, tz.getStandardOffset(between));
247                     assertEquals(expectedOffset, tz.getOffset(between));
248                 }
249             }
250         }
251     }
252 
253     public void testReverseTransitions() {
254         DateTimeZone tz = buildAmericaLosAngeles();
255         testReverseTransitions(tz, AMERICA_LOS_ANGELES_DATA);
256     }
257 
258     static void testReverseTransitions(DateTimeZone tz, String[][] data) {
259         long instant = new DateTime(data[data.length - 1][0]).getMillis();
260         for (int i=data.length; --i>=1; ) {
261             String[] row = data[i];
262             String[] prevRow = data[i - 1];
263             instant = tz.previousTransition(instant);
264 
265             long expectedInstant = new DateTime(row[0]).getMillis() - 1;
266             String expectedKey = prevRow[1];
267             int expectedStandardOffset = -(int) OFFSET_FORMATTER.parseMillis(prevRow[2]);
268             int expectedOffset = -(int) OFFSET_FORMATTER.parseMillis(prevRow[3]);
269 
270             assertEquals(expectedInstant, instant);
271             assertEquals(expectedKey, tz.getNameKey(instant));
272             assertEquals(expectedStandardOffset, tz.getStandardOffset(instant));
273             assertEquals(expectedOffset, tz.getOffset(instant));
274         }
275     }
276 
277     public void testSerialization() throws IOException {
278         DateTimeZone tz = testSerialization
279             (buildAmericaLosAngelesBuilder(), "America/Los_Angeles");
280 
281         assertEquals(false, tz.isFixed());
282         testForwardTransitions(tz, AMERICA_LOS_ANGELES_DATA);
283         testReverseTransitions(tz, AMERICA_LOS_ANGELES_DATA);
284     }
285 
286     static DateTimeZone testSerialization(DateTimeZoneBuilder builder, String id)
287         throws IOException
288     {
289         ByteArrayOutputStream out = new ByteArrayOutputStream();
290         builder.writeTo("America/Los_Angeles", out);
291         ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
292         DateTimeZone tz = DateTimeZoneBuilder.readFrom(in, id);
293         assertEquals(id, tz.getID());
294         return tz;
295     }
296 
297     public void testFixed() throws IOException {
298         DateTimeZoneBuilder builder = new DateTimeZoneBuilder()
299             .setStandardOffset(3600000)
300             .setFixedSavings("LMT", 0);
301         DateTimeZone tz = builder.toDateTimeZone("Test", true);
302 
303         for (int i=0; i<2; i++) {
304             assertEquals("Test", tz.getID());
305             assertEquals(true, tz.isFixed());
306             assertEquals(3600000, tz.getOffset(0));
307             assertEquals(3600000, tz.getStandardOffset(0));
308             assertEquals(0, tz.nextTransition(0));
309             assertEquals(0, tz.previousTransition(0));
310 
311             tz = testSerialization(builder, "Test");
312         }
313     }
314 }