1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 2003-2007, International Business Machines Corporation
4 * and others. All Rights Reserved.
5 ********************************************************************
6 * Calendar Case Test is a type of CalendarTest which compares the
7 * behavior of a calendar to a certain set of 'test cases', involving
8 * conversion between julian-day to fields and vice versa.
9 ********************************************************************/
10
11 #include "calcasts.h"
12
13 #if !UCONFIG_NO_FORMATTING
14 // ======= 'Main' ===========================
15
16 #include "hebrwcal.h" // for Eras
17 #include "indiancal.h"
18 #include "unicode/datefmt.h"
19
20 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
21
22
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)23 void CalendarCaseTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
24 {
25 if (exec) logln("TestSuite CalendarCaseTest");
26 switch (index) {
27 CASE(0,IslamicCivil);
28 CASE(1,Hebrew);
29 CASE(2,Indian);
30 default: name = ""; break;
31 }
32 }
33
34 #undef CASE
35
36 // ======= Utility functions =================
37
doTestCases(const TestCase * cases,Calendar * cal)38 void CalendarCaseTest::doTestCases(const TestCase *cases, Calendar *cal) {
39 static const int32_t ONE_SECOND = 1000;
40 static const int32_t ONE_MINUTE = 60*ONE_SECOND;
41 static const int32_t ONE_HOUR = 60*ONE_MINUTE;
42 static const double ONE_DAY = 24*ONE_HOUR;
43 static const double JULIAN_EPOCH = -210866760000000.; // 1/1/4713 BC 12:00
44 int32_t i;
45 UErrorCode status = U_ZERO_ERROR;
46 cal->adoptTimeZone(TimeZone::getGMT()->clone());
47 for(i=0;cases[i].era>=0;i++) {
48 UDate t = (JULIAN_EPOCH+(ONE_DAY*cases[i].julian));
49
50 logln("Test case %d: julianday%f -> date %f\n", i, cases[i].julian, t);
51
52 // Millis -> fields
53 cal->setTime(t, status);
54
55 logln(calToStr(*cal));
56
57 checkField(cal, UCAL_ERA, cases[i].era, status);
58 checkField(cal, UCAL_YEAR, cases[i].year,status);
59 checkField(cal, UCAL_MONTH, cases[i].month - 1,status);
60 checkField(cal, UCAL_DATE, cases[i].day,status);
61 checkField(cal, UCAL_DAY_OF_WEEK, cases[i].dayOfWeek,status);
62 checkField(cal, UCAL_HOUR, cases[i].hour,status);
63 checkField(cal, UCAL_MINUTE, cases[i].min,status);
64 checkField(cal, UCAL_SECOND, cases[i].sec,status);
65
66 // Fields -> millis
67 cal->clear();
68
69 cal->set(UCAL_ERA, cases[i].era);
70 cal->set(UCAL_YEAR, cases[i].year);
71 cal->set(UCAL_MONTH, cases[i].month - 1);
72 cal->set(UCAL_DATE, cases[i].day);
73 cal->set(UCAL_DAY_OF_WEEK, cases[i].dayOfWeek);
74 cal->set(UCAL_HOUR, cases[i].hour);
75 cal->set(UCAL_MINUTE, cases[i].min);
76 cal->set(UCAL_SECOND, cases[i].sec);
77
78 UDate t2 = cal->getTime(status);
79
80 if(t != t2) {
81 errln("Field->millis: Expected %.0f but got %.0f\n", t, t2);
82 logln(calToStr(*cal));
83 }
84 }
85 }
86
checkField(Calendar * cal,UCalendarDateFields field,int32_t value,UErrorCode & status)87 UBool CalendarCaseTest::checkField(Calendar *cal, UCalendarDateFields field, int32_t value, UErrorCode &status)
88 {
89 if(U_FAILURE(status)) return FALSE;
90 int32_t res = cal->get(field, status);
91 if(U_FAILURE(status)) {
92 errln((UnicodeString)"Checking field " + fieldName(field) + " and got " + u_errorName(status));
93 return FALSE;
94 }
95 if(res != value) {
96 errln((UnicodeString)"FAIL: Checking field " + fieldName(field) + " expected " + value + " and got " + res + UnicodeString("\n"));
97 return FALSE;
98 } else {
99 logln((UnicodeString)"Checking field " + fieldName(field) + " == " + value + UnicodeString("\n"));
100 }
101 return TRUE;
102 }
103
104 // =========== Test Cases =====================
105 enum { SUN=UCAL_SUNDAY,
106 MON=UCAL_MONDAY,
107 TUE=UCAL_TUESDAY,
108 WED=UCAL_WEDNESDAY,
109 THU=UCAL_THURSDAY,
110 FRI=UCAL_FRIDAY,
111 SAT=UCAL_SATURDAY};
112
IslamicCivil()113 void CalendarCaseTest::IslamicCivil()
114 {
115 static const TestCase tests[] = {
116 //
117 // Most of these test cases were taken from the back of
118 // "Calendrical Calculations", with some extras added to help
119 // debug a few of the problems that cropped up in development.
120 //
121 // The months in this table are 1-based rather than 0-based,
122 // because it's easier to edit that way.
123 // Islamic
124 // Julian Day Era Year Month Day WkDay Hour Min Sec
125 { 1507231.5, 0, -1245, 12, 9, SUN, 0, 0, 0},
126 { 1660037.5, 0, -813, 2, 23, WED, 0, 0, 0},
127 { 1746893.5, 0, -568, 4, 1, WED, 0, 0, 0},
128 { 1770641.5, 0, -501, 4, 6, SUN, 0, 0, 0},
129 { 1892731.5, 0, -157, 10, 17, WED, 0, 0, 0},
130 { 1931579.5, 0, -47, 6, 3, MON, 0, 0, 0},
131 { 1974851.5, 0, 75, 7, 13, SAT, 0, 0, 0},
132 { 2091164.5, 0, 403, 10, 5, SUN, 0, 0, 0},
133 { 2121509.5, 0, 489, 5, 22, SUN, 0, 0, 0},
134 { 2155779.5, 0, 586, 2, 7, FRI, 0, 0, 0},
135 { 2174029.5, 0, 637, 8, 7, SAT, 0, 0, 0},
136 { 2191584.5, 0, 687, 2, 20, FRI, 0, 0, 0},
137 { 2195261.5, 0, 697, 7, 7, SUN, 0, 0, 0},
138 { 2229274.5, 0, 793, 7, 1, SUN, 0, 0, 0},
139 { 2245580.5, 0, 839, 7, 6, WED, 0, 0, 0},
140 { 2266100.5, 0, 897, 6, 1, SAT, 0, 0, 0},
141 { 2288542.5, 0, 960, 9, 30, SAT, 0, 0, 0},
142 { 2290901.5, 0, 967, 5, 27, SAT, 0, 0, 0},
143 { 2323140.5, 0, 1058, 5, 18, WED, 0, 0, 0},
144 { 2334848.5, 0, 1091, 6, 2, SUN, 0, 0, 0},
145 { 2348020.5, 0, 1128, 8, 4, FRI, 0, 0, 0},
146 { 2366978.5, 0, 1182, 2, 3, SUN, 0, 0, 0},
147 { 2385648.5, 0, 1234, 10, 10, MON, 0, 0, 0},
148 { 2392825.5, 0, 1255, 1, 11, WED, 0, 0, 0},
149 { 2416223.5, 0, 1321, 1, 21, SUN, 0, 0, 0},
150 { 2425848.5, 0, 1348, 3, 19, SUN, 0, 0, 0},
151 { 2430266.5, 0, 1360, 9, 8, MON, 0, 0, 0},
152 { 2430833.5, 0, 1362, 4, 13, MON, 0, 0, 0},
153 { 2431004.5, 0, 1362, 10, 7, THU, 0, 0, 0},
154 { 2448698.5, 0, 1412, 9, 13, TUE, 0, 0, 0},
155 { 2450138.5, 0, 1416, 10, 5, SUN, 0, 0, 0},
156 { 2465737.5, 0, 1460, 10, 12, WED, 0, 0, 0},
157 { 2486076.5, 0, 1518, 3, 5, SUN, 0, 0, 0},
158 { -1,-1,-1,-1,-1,-1,-1,-1,-1 }
159 };
160
161 UErrorCode status = U_ZERO_ERROR;
162 Calendar *c = Calendar::createInstance("ar@calendar=islamic-civil", status);
163 c->setLenient(TRUE);
164 doTestCases(tests, c);
165
166 static const UChar expectedUChars[] = {
167 0x0627, 0x0644, 0x062e, 0x0645, 0x064a, 0x0633, 0x002c, 0x0020, 0x0662, 0x0662,
168 0x0020, 0x0634, 0x0648, 0x0627, 0x0644, 0x002c, 0x0020, 0x0661, 0x0663, 0x0668,
169 0x0669, 0
170 };
171 UnicodeString result;
172 DateFormat *fmt = DateFormat::createDateInstance(DateFormat::kFull, Locale("ar_JO@calendar=islamic-civil"));
173 if (fmt == NULL) {
174 dataerrln("Error calling DateFormat::createDateInstance");
175 delete c;
176 delete fmt;
177 return;
178 }
179
180 fmt->setTimeZone(*TimeZone::getGMT());
181 fmt->format((UDate)2486076.5, result);
182 if (result != expectedUChars) {
183 errln((UnicodeString)"FAIL: DateFormatting failed. Got " + result + " and expected " + UnicodeString(expectedUChars) + UnicodeString("\n"));
184 errln("Maybe the resource aliasing isn't working");
185 }
186 delete fmt;
187 delete c;
188 }
189
Hebrew()190 void CalendarCaseTest::Hebrew() {
191 static const int32_t TISHRI = HebrewCalendar::TISHRI;
192 //static const int32_t HESHVAN = HebrewCalendar::HESHVAN;
193 //static const int32_t KISLEV = HebrewCalendar::KISLEV;
194 //static const int32_t TEVET = HebrewCalendar::TEVET;
195 //static const int32_t SHEVAT = HebrewCalendar::SHEVAT;
196 //static const int32_t ADAR_1 = HebrewCalendar::ADAR_1;
197 //static const int32_t ADAR = HebrewCalendar::ADAR;
198 //static const int32_t NISAN = HebrewCalendar::NISAN;
199 //static const int32_t IYAR = HebrewCalendar::IYAR;
200 //static const int32_t SIVAN = HebrewCalendar::SIVAN;
201 //static const int32_t TAMUZ = HebrewCalendar::TAMUZ;
202 static const int32_t AV = HebrewCalendar::AV;
203 static const int32_t ELUL = HebrewCalendar::ELUL;
204
205 static const TestCase tests[] = {
206 //
207 // Most of these test cases were taken from the back of
208 // "Calendrical Calculations", with some extras added to help
209 // debug a few of the problems that cropped up in development.
210 //
211 // The months in this table are 1-based rather than 0-based,
212 // because it's easier to edit that way.
213 //
214 // Julian Day Era Year Month Day WkDay Hour Min Sec
215 {1507231.5, 0, 3174, 12, 10, SUN, 0, 0, 0},
216 {1660037.5, 0, 3593, 3, 25, WED, 0, 0, 0},
217 {1746893.5, 0, 3831, 1, 3, WED, 0, 0, 0},
218 {1770641.5, 0, 3896, 1, 9, SUN, 0, 0, 0},
219 {1892731.5, 0, 4230, 4, 18, WED, 0, 0, 0},
220 {1931579.5, 0, 4336, 10, 4, MON, 0, 0, 0},
221 {1974851.5, 0, 4455, 2, 13, SAT, 0, 0, 0},
222 {2091164.5, 0, 4773, 9, 6, SUN, 0, 0, 0},
223 {2121509.5, 0, 4856, 9, 23, SUN, 0, 0, 0},
224 {2155779.5, 0, 4950, 8, 7, FRI, 0, 0, 0},
225 {2174029.5, 0, 5000, 7, 8, SAT, 0, 0, 0},
226 {2191584.5, 0, 5048, 8, 21, FRI, 0, 0, 0},
227 {2195261.5, 0, 5058, 9, 7, SUN, 0, 0, 0},
228 {2229274.5, 0, 5151, 11, 1, SUN, 0, 0, 0},
229 {2245580.5, 0, 5196, 5, 7, WED, 0, 0, 0},
230 {2266100.5, 0, 5252, 8, 3, SAT, 0, 0, 0},
231 {2288542.5, 0, 5314, 1, 1, SAT, 0, 0, 0},
232 {2290901.5, 0, 5320, 6, 27, SAT, 0, 0, 0},
233 {2323140.5, 0, 5408, 10, 20, WED, 0, 0, 0},
234 {2334551.5, 0, 5440, 1, 1, THU, 0, 0, 0},
235 {2334581.5, 0, 5440, 2, 1, SAT, 0, 0, 0},
236 {2334610.5, 0, 5440, 3, 1, SUN, 0, 0, 0},
237 {2334639.5, 0, 5440, 4, 1, MON, 0, 0, 0},
238 {2334668.5, 0, 5440, 5, 1, TUE, 0, 0, 0},
239 {2334698.5, 0, 5440, 6, 1, THU, 0, 0, 0},
240 {2334728.5, 0, 5440, 7, 1, SAT, 0, 0, 0},
241 {2334757.5, 0, 5440, 8, 1, SUN, 0, 0, 0},
242 {2334787.5, 0, 5440, 9, 1, TUE, 0, 0, 0},
243 {2334816.5, 0, 5440, 10, 1, WED, 0, 0, 0},
244 {2334846.5, 0, 5440, 11, 1, FRI, 0, 0, 0},
245 {2334848.5, 0, 5440, 11, 3, SUN, 0, 0, 0},
246 {2334934.5, 0, 5441, 1, 1, TUE, 0, 0, 0},
247 {2348020.5, 0, 5476, 12, 5, FRI, 0, 0, 0},
248 {2366978.5, 0, 5528, 11, 4, SUN, 0, 0, 0},
249 {2385648.5, 0, 5579, 12, 11, MON, 0, 0, 0},
250 {2392825.5, 0, 5599, 8, 12, WED, 0, 0, 0},
251 {2416223.5, 0, 5663, 8, 22, SUN, 0, 0, 0},
252 {2425848.5, 0, 5689, 12, 19, SUN, 0, 0, 0},
253 {2430266.5, 0, 5702, 1, 8, MON, 0, 0, 0},
254 {2430833.5, 0, 5703, 8, 14, MON, 0, 0, 0},
255 {2431004.5, 0, 5704, 1, 8, THU, 0, 0, 0},
256 {2448698.5, 0, 5752, 7, 12, TUE, 0, 0, 0},
257 {2450138.5, 0, 5756, 7, 5, SUN, 0, 0, 0},
258 {2465737.5, 0, 5799, 2, 12, WED, 0, 0, 0},
259 {2486076.5, 0, 5854, 12, 5, SUN, 0, 0, 0},
260
261 // Test cases taken from a table of 14 "year types" in the Help file
262 // of the application "Hebrew Calendar"
263 {2456187.5, 0, 5773, 1, 1, MON, 0, 0, 0},
264 {2459111.5, 0, 5781, 1, 1, SAT, 0, 0, 0},
265 {2453647.5, 0, 5766, 1, 1, TUE, 0, 0, 0},
266 {2462035.5, 0, 5789, 1, 1, THU, 0, 0, 0},
267 {2458756.5, 0, 5780, 1, 1, MON, 0, 0, 0},
268 {2460586.5, 0, 5785, 1, 1, THU, 0, 0, 0},
269 {2463864.5, 0, 5794, 1, 1, SAT, 0, 0, 0},
270 {2463481.5, 0, 5793, 1, 1, MON, 0, 0, 0},
271 {2470421.5, 0, 5812, 1, 1, THU, 0, 0, 0},
272 {2460203.5, 0, 5784, 1, 1, SAT, 0, 0, 0},
273 {2459464.5, 0, 5782, 1, 1, TUE, 0, 0, 0},
274 {2467142.5, 0, 5803, 1, 1, MON, 0, 0, 0},
275 {2455448.5, 0, 5771, 1, 1, THU, 0, 0, 0},
276 // Test cases for JB#2327
277 // http://www.fourmilab.com/documents/calendar/
278 // http://www.calendarhome.com/converter/
279 // 2452465.5, 2002, JULY, 10, 5762, AV, 1,
280 // 2452494.5, 2002, AUGUST, 8, 5762, AV, 30,
281 // 2452495.5, 2002, AUGUST, 9, 5762, ELUL, 1,
282 // 2452523.5, 2002, SEPTEMBER, 6, 5762, ELUL, 29,
283 // 2452524.5, 2002, SEPTEMBER, 7, 5763, TISHRI, 1,
284 // Julian Day Era Year Month Day WkDay Hour Min Sec
285 {2452465.5, 0, 5762, AV+1, 1, WED, 0, 0, 0},
286 {2452494.5, 0, 5762, AV+1, 30, THU, 0, 0, 0},
287 {2452495.5, 0, 5762, ELUL+1, 1, FRI, 0, 0, 0},
288 {2452523.5, 0, 5762, ELUL+1, 29, FRI, 0, 0, 0},
289 {2452524.5, 0, 5763, TISHRI+1, 1, SAT, 0, 0, 0},
290 { -1,-1,-1,-1,-1,-1,-1,-1,-1 }
291 };
292
293 UErrorCode status = U_ZERO_ERROR;
294 Calendar *c = Calendar::createInstance("he_HE@calendar=hebrew", status);
295 c->setLenient(TRUE);
296 doTestCases(tests, c);
297
298
299 // Additional test cases for bugs found during development
300 // G.YY/MM/DD Era Year Month Day WkDay Hour Min Sec
301 //{1013, 9, 8, 0, 4774, 1, 1, TUE, 0, 0, 0},
302 //{1239, 9, 1, 0, 5000, 1, 1, THU, 0, 0, 0},
303 //{1240, 9,18, 0, 5001, 1, 1, TUE, 0, 0, 0},
304
305
306 delete c;
307 }
308
Indian()309 void CalendarCaseTest::Indian() {
310 // Months in indian calendar are 0-based. Here taking 1-based names:
311 static const int32_t CHAITRA = IndianCalendar::CHAITRA + 1;
312 static const int32_t VAISAKHA = IndianCalendar::VAISAKHA + 1;
313 static const int32_t JYAISTHA = IndianCalendar::JYAISTHA + 1;
314 static const int32_t ASADHA = IndianCalendar::ASADHA + 1;
315 static const int32_t SRAVANA = IndianCalendar::SRAVANA + 1 ;
316 static const int32_t BHADRA = IndianCalendar::BHADRA + 1 ;
317 static const int32_t ASVINA = IndianCalendar::ASVINA + 1 ;
318 static const int32_t KARTIKA = IndianCalendar::KARTIKA + 1 ;
319 static const int32_t AGRAHAYANA = IndianCalendar::AGRAHAYANA + 1 ;
320 static const int32_t PAUSA = IndianCalendar::PAUSA + 1 ;
321 static const int32_t MAGHA = IndianCalendar::MAGHA + 1 ;
322 static const int32_t PHALGUNA = IndianCalendar::PHALGUNA + 1 ;
323
324
325 static const TestCase tests[] = {
326 // Test dates generated from:
327 // http://www.fourmilab.ch/documents/calendar/
328
329 // A huge list of test cases to make sure that computeTime and computeFields
330 // work properly for a wide range of data in the Indian civil calendar.
331 //
332 // Julian Day Era Year Month Day WkDay Hour Min Sec
333 {1770641.5, 0, 57, ASVINA, 10, SUN, 0, 0, 0},
334 {1892731.5, 0, 391, PAUSA, 18, WED, 0, 0, 0},
335 {1931579.5, 0, 498, VAISAKHA, 30, MON, 0, 0, 0},
336 {1974851.5, 0, 616, KARTIKA, 19, SAT, 0, 0, 0},
337 {2091164.5, 0, 935, VAISAKHA, 5, SUN, 0, 0, 0},
338 {2121509.5, 0, 1018, JYAISTHA, 3, SUN, 0, 0, 0},
339 {2155779.5, 0, 1112, CHAITRA, 2, FRI, 0, 0, 0},
340 {2174029.5, 0, 1161, PHALGUNA, 20, SAT, 0, 0, 0},
341 {2191584.5, 0, 1210, CHAITRA, 13, FRI, 0, 0, 0},
342 {2195261.5, 0, 1220, VAISAKHA, 7, SUN, 0, 0, 0},
343 {2229274.5, 0, 1313, JYAISTHA, 22, SUN, 0, 0, 0},
344 {2245580.5, 0, 1357, MAGHA, 14, WED, 0, 0, 0},
345 {2266100.5, 0, 1414, CHAITRA, 20, SAT, 0, 0, 0},
346 {2288542.5, 0, 1475, BHADRA, 28, SAT, 0, 0, 0},
347 {2290901.5, 0, 1481, PHALGUNA, 15, SAT, 0, 0, 0},
348 {2323140.5, 0, 1570, JYAISTHA, 20, WED, 0, 0, 0},
349 {2334551.5, 0, 1601, BHADRA, 16, THU, 0, 0, 0},
350 {2334581.5, 0, 1601, ASVINA, 15, SAT, 0, 0, 0},
351 {2334610.5, 0, 1601, KARTIKA, 14, SUN, 0, 0, 0},
352 {2334639.5, 0, 1601, AGRAHAYANA, 13, MON, 0, 0, 0},
353 {2334668.5, 0, 1601, PAUSA, 12, TUE, 0, 0, 0},
354 {2334698.5, 0, 1601, MAGHA, 12, THU, 0, 0, 0},
355 {2334728.5, 0, 1601, PHALGUNA, 12, SAT, 0, 0, 0},
356 {2334757.5, 0, 1602, CHAITRA, 11, SUN, 0, 0, 0},
357 {2334787.5, 0, 1602, VAISAKHA, 10, TUE, 0, 0, 0},
358 {2334816.5, 0, 1602, JYAISTHA, 8, WED, 0, 0, 0},
359 {2334846.5, 0, 1602, ASADHA, 7, FRI, 0, 0, 0},
360 {2334848.5, 0, 1602, ASADHA, 9, SUN, 0, 0, 0},
361 {2348020.5, 0, 1638, SRAVANA, 2, FRI, 0, 0, 0},
362 {2334934.5, 0, 1602, ASVINA, 2, TUE, 0, 0, 0},
363 {2366978.5, 0, 1690, JYAISTHA, 29, SUN, 0, 0, 0},
364 {2385648.5, 0, 1741, SRAVANA, 11, MON, 0, 0, 0},
365 {2392825.5, 0, 1761, CHAITRA, 6, WED, 0, 0, 0},
366 {2416223.5, 0, 1825, CHAITRA, 29, SUN, 0, 0, 0},
367 {2425848.5, 0, 1851, BHADRA, 3, SUN, 0, 0, 0},
368 {2430266.5, 0, 1863, ASVINA, 7, MON, 0, 0, 0},
369 {2430833.5, 0, 1865, CHAITRA, 29, MON, 0, 0, 0},
370 {2431004.5, 0, 1865, ASVINA, 15, THU, 0, 0, 0},
371 {2448698.5, 0, 1913, PHALGUNA, 27, TUE, 0, 0, 0},
372 {2450138.5, 0, 1917, PHALGUNA, 6, SUN, 0, 0, 0},
373 {2465737.5, 0, 1960, KARTIKA, 19, WED, 0, 0, 0},
374 {2486076.5, 0, 2016, ASADHA, 27, SUN, 0, 0, 0},
375 { -1,-1,-1,-1,-1,-1,-1,-1,-1 }
376 };
377
378 UErrorCode status = U_ZERO_ERROR;
379 Calendar *c = Calendar::createInstance("hi_IN@calendar=indian", status);
380 c->setLenient(TRUE);
381 doTestCases(tests, c);
382
383 delete c;
384 }
385
386 #endif
387