001 /*
002 * Copyright 2001-2005 Stephen Colebourne
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.joda.time.tz;
017
018 import java.io.ByteArrayInputStream;
019 import java.io.ByteArrayOutputStream;
020 import java.io.IOException;
021
022 import junit.framework.TestCase;
023 import junit.framework.TestSuite;
024
025 import org.joda.time.DateTime;
026 import org.joda.time.DateTimeZone;
027 import org.joda.time.format.DateTimeFormatter;
028 import org.joda.time.format.DateTimeFormatterBuilder;
029
030 /**
031 * Test cases for DateTimeZoneBuilder.
032 *
033 * @author Brian S O'Neill
034 */
035 public class TestBuilder extends TestCase {
036 public static void main(String[] args) {
037 junit.textui.TestRunner.run(suite());
038 }
039
040 public static TestSuite suite() {
041 return new TestSuite(TestBuilder.class);
042 }
043
044 static final DateTimeFormatter OFFSET_FORMATTER = new DateTimeFormatterBuilder()
045 .appendTimeZoneOffset(null, true, 2, 4)
046 .toFormatter();
047
048 // Each row is {transition, nameKey, standardOffset, offset}
049 static final String[][] AMERICA_LOS_ANGELES_DATA = {
050 {null, "LMT", "-07:52:58", "-07:52:58"},
051 {"1883-11-18T19:52:58.000Z", "PST", "-08:00", "-08:00"},
052 {"1918-03-31T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
053 {"1918-10-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
054 {"1919-03-30T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
055 {"1919-10-26T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
056 {"1942-02-09T02:00:00.000-08:00", "PWT", "-08:00", "-07:00"},
057 {"1945-08-14T23:00:00.000Z", "PPT", "-08:00", "-07:00"},
058 {"1945-09-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
059 {"1948-03-14T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
060 {"1949-01-01T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
061 {"1950-04-30T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
062 {"1950-09-24T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
063 {"1951-04-29T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
064 {"1951-09-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
065 {"1952-04-27T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
066 {"1952-09-28T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
067 {"1953-04-26T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
068 {"1953-09-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
069 {"1954-04-25T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
070 {"1954-09-26T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
071 {"1955-04-24T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
072 {"1955-09-25T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
073 {"1956-04-29T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
074 {"1956-09-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
075 {"1957-04-28T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
076 {"1957-09-29T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
077 {"1958-04-27T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
078 {"1958-09-28T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
079 {"1959-04-26T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
080 {"1959-09-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
081 {"1960-04-24T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
082 {"1960-09-25T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
083 {"1961-04-30T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
084 {"1961-09-24T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
085 {"1962-04-29T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
086 {"1962-10-28T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
087 {"1963-04-28T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
088 {"1963-10-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
089 {"1964-04-26T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
090 {"1964-10-25T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
091 {"1965-04-25T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
092 {"1965-10-31T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
093 {"1966-04-24T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
094 {"1966-10-30T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
095 {"1967-04-30T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
096 {"1967-10-29T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
097 {"1968-04-28T02:00:00.000-08:00", "PDT", "-08:00", "-07:00"},
098 {"1968-10-27T02:00:00.000-07:00", "PST", "-08:00", "-08:00"},
099 {"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 }