1 /*
2  *******************************************************************************
3  * Copyright (C) 2007-2008, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 package com.ibm.icu.dev.test.timezone;
8 
9 import java.util.Date;
10 
11 import com.ibm.icu.dev.test.TestFmwk;
12 import com.ibm.icu.text.DateFormat;
13 import com.ibm.icu.util.AnnualTimeZoneRule;
14 import com.ibm.icu.util.BasicTimeZone;
15 import com.ibm.icu.util.Calendar;
16 import com.ibm.icu.util.DateTimeRule;
17 import com.ibm.icu.util.GregorianCalendar;
18 import com.ibm.icu.util.InitialTimeZoneRule;
19 import com.ibm.icu.util.RuleBasedTimeZone;
20 import com.ibm.icu.util.SimpleTimeZone;
21 import com.ibm.icu.util.TimeZone;
22 
23 /**
24  * Testing getOffset APIs using local time
25  */
26 public class TimeZoneOffsetLocalTest extends TestFmwk {
27 
main(String[] args)28     public static void main(String[] args) throws Exception {
29         new TimeZoneOffsetLocalTest().run(args);
30     }
31 
32     /*
33      * Testing getOffset APIs around rule transition by local standard/wall time.
34      */
TestGetOffsetAroundTransition()35     public void TestGetOffsetAroundTransition() {
36         final int HOUR = 60*60*1000;
37         final int MINUTE = 60*1000;
38 
39         int[][] DATES = {
40             {2006, Calendar.APRIL, 2, 1, 30, 1*HOUR+30*MINUTE},
41             {2006, Calendar.APRIL, 2, 2, 00, 2*HOUR},
42             {2006, Calendar.APRIL, 2, 2, 30, 2*HOUR+30*MINUTE},
43             {2006, Calendar.APRIL, 2, 3, 00, 3*HOUR},
44             {2006, Calendar.APRIL, 2, 3, 30, 3*HOUR+30*MINUTE},
45             {2006, Calendar.OCTOBER, 29, 0, 30, 0*HOUR+30*MINUTE},
46             {2006, Calendar.OCTOBER, 29, 1, 00, 1*HOUR},
47             {2006, Calendar.OCTOBER, 29, 1, 30, 1*HOUR+30*MINUTE},
48             {2006, Calendar.OCTOBER, 29, 2, 00, 2*HOUR},
49             {2006, Calendar.OCTOBER, 29, 2, 30, 2*HOUR+30*MINUTE},
50         };
51 
52         // Expected offsets by getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds)
53         int[] OFFSETS1 = {
54             // April 2, 2006
55             -8*HOUR,
56             -7*HOUR,
57             -7*HOUR,
58             -7*HOUR,
59             -7*HOUR,
60 
61             // October 29, 2006
62             -7*HOUR,
63             -8*HOUR,
64             -8*HOUR,
65             -8*HOUR,
66             -8*HOUR,
67         };
68 
69 
70         // Expected offsets by getOffset(long time, boolean local, int[] offsets) with local = true
71         // or getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
72         // with nonExistingTimeOpt = LOCAL_STD/duplicatedTimeOpt = LOCAL_STD
73         int[][] OFFSETS2 = {
74             // April 2, 2006
75             {-8*HOUR, 0},
76             {-8*HOUR, 0},
77             {-8*HOUR, 0},
78             {-8*HOUR, 1*HOUR},
79             {-8*HOUR, 1*HOUR},
80 
81             // Oct 29, 2006
82             {-8*HOUR, 1*HOUR},
83             {-8*HOUR, 0},
84             {-8*HOUR, 0},
85             {-8*HOUR, 0},
86             {-8*HOUR, 0},
87         };
88 
89         // Expected offsets by getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
90         // with nonExistingTimeOpt = LOCAL_DST/duplicatedTimeOpt = LOCAL_DST
91         int[][] OFFSETS3 = {
92             // April 2, 2006
93             {-8*HOUR, 0},
94             {-8*HOUR, 1*HOUR},
95             {-8*HOUR, 1*HOUR},
96             {-8*HOUR, 1*HOUR},
97             {-8*HOUR, 1*HOUR},
98 
99             // October 29, 2006
100             {-8*HOUR, 1*HOUR},
101             {-8*HOUR, 1*HOUR},
102             {-8*HOUR, 1*HOUR},
103             {-8*HOUR, 0},
104             {-8*HOUR, 0},
105         };
106 
107         int[] offsets = new int[2];
108 
109         TimeZone utc = TimeZone.getTimeZone("UTC");
110         Calendar cal = Calendar.getInstance(utc);
111         cal.clear();
112 
113         // Set up TimeZone objects - OlsonTimeZone, SimpleTimeZone and RuleBasedTimeZone
114         BasicTimeZone[] TESTZONES = new BasicTimeZone[3];
115 
116         TESTZONES[0] = (BasicTimeZone)TimeZone.getTimeZone("America/Los_Angeles", TimeZone.TIMEZONE_ICU);
117         TESTZONES[1] = new SimpleTimeZone(-8*HOUR, "Simple Pacific Time",
118                                             Calendar.APRIL, 1, Calendar.SUNDAY, 2*HOUR,
119                                             Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*HOUR);
120 
121         InitialTimeZoneRule ir = new InitialTimeZoneRule(
122                 "Pacific Standard Time", // Initial time Name
123                 -8*HOUR,        // Raw offset
124                 0*HOUR);        // DST saving amount
125 
126         RuleBasedTimeZone rbPT = new RuleBasedTimeZone("Rule based Pacific Time", ir);
127 
128         DateTimeRule dtr;
129         AnnualTimeZoneRule atzr;
130         final int STARTYEAR = 2000;
131 
132         dtr = new DateTimeRule(Calendar.APRIL, 1, Calendar.SUNDAY,
133                 2*HOUR, DateTimeRule.WALL_TIME); // 1st Sunday in April, at 2AM wall time
134         atzr = new AnnualTimeZoneRule("Pacific Daylight Time",
135                 -8*HOUR /* rawOffset */, 1*HOUR /* dstSavings */, dtr,
136                 STARTYEAR, AnnualTimeZoneRule.MAX_YEAR);
137         rbPT.addTransitionRule(atzr);
138 
139         dtr = new DateTimeRule(Calendar.OCTOBER, -1, Calendar.SUNDAY,
140                 2*HOUR, DateTimeRule.WALL_TIME); // last Sunday in October, at 2AM wall time
141         atzr = new AnnualTimeZoneRule("Pacific Standard Time",
142                 -8*HOUR /* rawOffset */, 0 /* dstSavings */, dtr,
143                 STARTYEAR, AnnualTimeZoneRule.MAX_YEAR);
144         rbPT.addTransitionRule(atzr);
145 
146         TESTZONES[2] = rbPT;
147 
148         // Calculate millis
149         long [] MILLIS = new long[DATES.length];
150         for (int i = 0; i < DATES.length; i++) {
151             cal.clear();
152             cal.set(DATES[i][0], DATES[i][1], DATES[i][2], DATES[i][3], DATES[i][4]);
153             MILLIS[i] = cal.getTimeInMillis();
154         }
155 
156         DateFormat df = DateFormat.getInstance();
157         df.setTimeZone(utc);
158 
159         // Test getOffset(int era, int year, int month, int day, int dayOfWeek, int millis)
160         for (int i = 0; i < TESTZONES.length; i++) {
161             for (int d = 0; d < DATES.length; d++) {
162                 int offset = TESTZONES[i].getOffset(GregorianCalendar.AD, DATES[d][0], DATES[d][1], DATES[d][2],
163                                                     Calendar.SUNDAY, DATES[d][5]);
164                 if (offset != OFFSETS1[d]) {
165                     errln("Bad offset returned by " + TESTZONES[i].getID() + " at "
166                             + df.format(new Date(MILLIS[d])) + "(standard) - Got: " + offset + " Expected: " + OFFSETS1[d]);
167                 }
168             }
169         }
170 
171         // Test getOffset(long time, boolean local, int[] offsets) with local=true
172         for (int i = 0; i < TESTZONES.length; i++) {
173             for (int m = 0; m < MILLIS.length; m++) {
174                 TESTZONES[i].getOffset(MILLIS[m], true, offsets);
175                 if (offsets[0] != OFFSETS2[m][0] || offsets[1] != OFFSETS2[m][1]) {
176                     errln("Bad offset returned by " + TESTZONES[i].getID() + " at "
177                             + df.format(new Date(MILLIS[m])) + "(wall) - Got: "
178                             + offsets[0] + "/" + offsets[1]
179                             + " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]);
180                 }
181             }
182         }
183 
184         // Test getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
185         // with nonExistingTimeOpt = LOCAL_STD/duplicatedTimeOpt = LOCAL_STD
186         for (int i = 0; i < TESTZONES.length; i++) {
187             for (int m = 0; m < MILLIS.length; m++) {
188                 TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_STD, BasicTimeZone.LOCAL_STD, offsets);
189                 if (offsets[0] != OFFSETS2[m][0] || offsets[1] != OFFSETS2[m][1]) {
190                     errln("Bad offset returned by " + TESTZONES[i].getID() + " at "
191                             + df.format(new Date(MILLIS[m])) + "(wall/STD/STD) - Got: "
192                             + offsets[0] + "/" + offsets[1]
193                             + " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]);
194                 }
195             }
196         }
197 
198         // Test getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
199         // with nonExistingTimeOpt = LOCAL_DST/duplicatedTimeOpt = LOCAL_DST
200         for (int i = 0; i < TESTZONES.length; i++) {
201             for (int m = 0; m < MILLIS.length; m++) {
202                 TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_DST, BasicTimeZone.LOCAL_DST, offsets);
203                 if (offsets[0] != OFFSETS3[m][0] || offsets[1] != OFFSETS3[m][1]) {
204                     errln("Bad offset returned by " + TESTZONES[i].getID() + " at "
205                             + df.format(new Date(MILLIS[m])) + "(wall/DST/DST) - Got: "
206                             + offsets[0] + "/" + offsets[1]
207                             + " Expected: " + OFFSETS3[m][0] + "/" + OFFSETS3[m][1]);
208                 }
209             }
210         }
211 
212         // Test getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
213         // with nonExistingTimeOpt = LOCAL_FORMER/duplicatedTimeOpt = LOCAL_LATTER
214         for (int i = 0; i < TESTZONES.length; i++) {
215             for (int m = 0; m < MILLIS.length; m++) {
216                 TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_FORMER, BasicTimeZone.LOCAL_LATTER, offsets);
217                 if (offsets[0] != OFFSETS2[m][0] || offsets[1] != OFFSETS2[m][1]) {
218                     errln("Bad offset returned by " + TESTZONES[i].getID() + " at "
219                             + df.format(new Date(MILLIS[m])) + "(wall/FORMER/LATTER) - Got: "
220                             + offsets[0] + "/" + offsets[1]
221                             + " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]);
222                 }
223             }
224         }
225 
226         // Test getOffsetFromLocal(long time, int nonExistingTimeOpt, int duplicatedTimeOpt, int[] offsets)
227         // with nonExistingTimeOpt = LOCAL_LATTER/duplicatedTimeOpt = LOCAL_FORMER
228         for (int i = 0; i < TESTZONES.length; i++) {
229             for (int m = 0; m < MILLIS.length; m++) {
230                 TESTZONES[i].getOffsetFromLocal(MILLIS[m], BasicTimeZone.LOCAL_LATTER, BasicTimeZone.LOCAL_FORMER, offsets);
231                 if (offsets[0] != OFFSETS3[m][0] || offsets[1] != OFFSETS3[m][1]) {
232                     errln("Bad offset returned by " + TESTZONES[i].getID() + " at "
233                             + df.format(new Date(MILLIS[m])) + "(wall/LATTER/FORMER) - Got: "
234                             + offsets[0] + "/" + offsets[1]
235                             + " Expected: " + OFFSETS3[m][0] + "/" + OFFSETS3[m][1]);
236                 }
237             }
238         }
239     }
240 }
241