• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * Copyright (c) 1997-2016, International Business Machines
5  * Corporation and others. All Rights Reserved.
6  ********************************************************************
7  *
8  * File CCALTST.C
9  *
10  * Modification History:
11  *        Name                     Description
12  *     Madhu Katragadda               Creation
13  ********************************************************************
14  */
15 
16 /* C API AND FUNCTIONALITY TEST FOR CALENDAR (ucol.h)*/
17 
18 #include "unicode/utypes.h"
19 
20 #if !UCONFIG_NO_FORMATTING
21 
22 #include <stdbool.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "unicode/uloc.h"
27 #include "unicode/ucal.h"
28 #include "unicode/udat.h"
29 #include "unicode/ustring.h"
30 #include "cintltst.h"
31 #include "ccaltst.h"
32 #include "cformtst.h"
33 #include "cmemory.h"
34 #include "cstring.h"
35 #include "ulist.h"
36 
37 void TestGregorianChange(void);
38 void TestFieldDifference(void);
39 void TestAddRollEra0AndEraBounds(void);
40 void TestGetTZTransition(void);
41 void TestGetWindowsTimeZoneID(void);
42 void TestGetTimeZoneIDByWindowsID(void);
43 void TestJpnCalAddSetNextEra(void);
44 void TestUcalOpenBufferRead(void);
45 void TestGetTimeZoneOffsetFromLocal(void);
46 
47 void addCalTest(TestNode** root);
48 
addCalTest(TestNode ** root)49 void addCalTest(TestNode** root)
50 {
51 
52     addTest(root, &TestCalendar, "tsformat/ccaltst/TestCalendar");
53     addTest(root, &TestGetSetDateAPI, "tsformat/ccaltst/TestGetSetDateAPI");
54     addTest(root, &TestFieldGetSet, "tsformat/ccaltst/TestFieldGetSet");
55     addTest(root, &TestAddRollExtensive, "tsformat/ccaltst/TestAddRollExtensive");
56     addTest(root, &TestGetLimits, "tsformat/ccaltst/TestGetLimits");
57     addTest(root, &TestDOWProgression, "tsformat/ccaltst/TestDOWProgression");
58     addTest(root, &TestGMTvsLocal, "tsformat/ccaltst/TestGMTvsLocal");
59     addTest(root, &TestGregorianChange, "tsformat/ccaltst/TestGregorianChange");
60     addTest(root, &TestGetKeywordValuesForLocale, "tsformat/ccaltst/TestGetKeywordValuesForLocale");
61     addTest(root, &TestWeekend, "tsformat/ccaltst/TestWeekend");
62     addTest(root, &TestFieldDifference, "tsformat/ccaltst/TestFieldDifference");
63     addTest(root, &TestAmbiguousWallTime, "tsformat/ccaltst/TestAmbiguousWallTime");
64     addTest(root, &TestAddRollEra0AndEraBounds, "tsformat/ccaltst/TestAddRollEra0AndEraBounds");
65     addTest(root, &TestGetTZTransition, "tsformat/ccaltst/TestGetTZTransition");
66     addTest(root, &TestGetWindowsTimeZoneID, "tsformat/ccaltst/TestGetWindowsTimeZoneID");
67     addTest(root, &TestGetTimeZoneIDByWindowsID, "tsformat/ccaltst/TestGetTimeZoneIDByWindowsID");
68     addTest(root, &TestJpnCalAddSetNextEra, "tsformat/ccaltst/TestJpnCalAddSetNextEra");
69     addTest(root, &TestUcalOpenBufferRead, "tsformat/ccaltst/TestUcalOpenBufferRead");
70     addTest(root, &TestGetTimeZoneOffsetFromLocal, "tsformat/ccaltst/TestGetTimeZoneOffsetFromLocal");
71 }
72 
73 /* "GMT" */
74 static const UChar fgGMTID [] = { 0x0047, 0x004d, 0x0054, 0x0000 };
75 
76 /* "PST" */
77 static const UChar PST[] = {0x50, 0x53, 0x54, 0x00}; /* "PST" */
78 
79 static const UChar EUROPE_PARIS[] = {0x45, 0x75, 0x72, 0x6F, 0x70, 0x65, 0x2F, 0x50, 0x61, 0x72, 0x69, 0x73, 0x00}; /* "Europe/Paris" */
80 
81 static const UChar AMERICA_LOS_ANGELES[] = {0x41, 0x6D, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2F,
82     0x4C, 0x6F, 0x73, 0x5F, 0x41, 0x6E, 0x67, 0x65, 0x6C, 0x65, 0x73, 0x00}; /* America/Los_Angeles */
83 
84 typedef struct {
85     const char *    locale;
86     UCalendarType   calType;
87     const char *    expectedResult;
88 } UCalGetTypeTest;
89 
90 static const UCalGetTypeTest ucalGetTypeTests[] = {
91     { "en_US",                   UCAL_GREGORIAN, "gregorian" },
92     { "ja_JP@calendar=japanese", UCAL_DEFAULT,   "japanese"  },
93     { "th_TH",                   UCAL_GREGORIAN, "gregorian" },
94     { "th_TH",                   UCAL_DEFAULT,   "buddhist"  },
95     { "th-TH-u-ca-gregory",      UCAL_DEFAULT,   "gregorian" },
96     { "ja_JP@calendar=japanese", UCAL_GREGORIAN, "gregorian" },
97     { "fr_CH",                   UCAL_DEFAULT,   "gregorian" },
98     { "fr_SA",                   UCAL_DEFAULT,   "islamic-umalqura" },
99     { "fr_CH@rg=sazzzz",         UCAL_DEFAULT,   "islamic-umalqura" },
100     { "fr_CH@calendar=japanese;rg=sazzzz", UCAL_DEFAULT, "japanese" },
101     { "fr_TH@rg=SA",             UCAL_DEFAULT,   "buddhist"  }, /* ignore malformed rg tag */
102     { "th@rg=SA",                UCAL_DEFAULT,   "buddhist"  }, /* ignore malformed rg tag */
103     { "",                        UCAL_GREGORIAN, "gregorian" },
104     { NULL,                      UCAL_GREGORIAN, "gregorian" },
105     { NULL, 0, NULL } /* terminator */
106 };
107 
TestCalendar()108 static void TestCalendar()
109 {
110     UCalendar *caldef = 0, *caldef2 = 0, *calfr = 0, *calit = 0, *calfrclone = 0;
111     UEnumeration* uenum = NULL;
112     int32_t count, count2, i,j;
113     UChar tzID[4];
114     UChar *tzdname = 0;
115     UErrorCode status = U_ZERO_ERROR;
116     UDate now;
117     UDateFormat *datdef = 0;
118     UChar *result = 0;
119     int32_t resultlength, resultlengthneeded;
120     char tempMsgBuf[1024];  // u_austrcpy() of some formatted dates & times.
121     char tempMsgBuf2[256];  // u_austrcpy() of some formatted dates & times.
122     UChar zone1[64], zone2[64];
123     const char *tzver = 0;
124     int32_t tzverLen = 0;
125     UChar canonicalID[64];
126     UBool isSystemID = false;
127     const UCalGetTypeTest * ucalGetTypeTestPtr;
128 
129 #ifdef U_USE_UCAL_OBSOLETE_2_8
130     /*Testing countAvailableTimeZones*/
131     int32_t offset=0;
132     log_verbose("\nTesting ucal_countAvailableTZIDs\n");
133     count=ucal_countAvailableTZIDs(offset);
134     log_verbose("The number of timezone id's present with offset 0 are %d:\n", count);
135     if(count < 5) /* Don't hard code an exact == test here! */
136         log_err("FAIL: error in the ucal_countAvailableTZIDs - got %d expected at least 5 total\n", count);
137 
138     /*Testing getAvailableTZIDs*/
139     log_verbose("\nTesting ucal_getAvailableTZIDs");
140     for(i=0;i<count;i++){
141         ucal_getAvailableTZIDs(offset, i, &status);
142         if(U_FAILURE(status)){
143             log_err("FAIL: ucal_getAvailableTZIDs returned %s\n", u_errorName(status));
144         }
145         log_verbose("%s\n", u_austrcpy(tempMsgBuf, ucal_getAvailableTZIDs(offset, i, &status)));
146     }
147     /*get Illegal TZID where index >= count*/
148     ucal_getAvailableTZIDs(offset, i, &status);
149     if(status != U_INDEX_OUTOFBOUNDS_ERROR){
150         log_err("FAIL:for TZID index >= count Expected INDEX_OUTOFBOUNDS_ERROR Got %s\n", u_errorName(status));
151     }
152     status=U_ZERO_ERROR;
153 #endif
154 
155     /*Test ucal_openTimeZones, ucal_openCountryTimeZones and ucal_openTimeZoneIDEnumeration */
156     for (j=0; j<6; ++j) {
157         const char *api = "?";
158         const int32_t offsetMinus5 = -5*60*60*1000;
159         switch (j) {
160         case 0:
161             api = "ucal_openTimeZones()";
162             uenum = ucal_openTimeZones(&status);
163             break;
164         case 1:
165             api = "ucal_openCountryTimeZones(US)";
166             uenum = ucal_openCountryTimeZones("US", &status);
167             break;
168         case 2:
169             api = "ucal_openTimeZoneIDEnumerarion(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL)";
170             uenum = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, &status);
171             break;
172         case 3:
173             api = "ucal_openTimeZoneIDEnumerarion(UCAL_ZONE_TYPE_CANONICAL_LOCATION, CA, NULL)";
174             uenum = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL_LOCATION, "CA", NULL, &status);
175             break;
176         case 4:
177             api = "ucal_openTimeZoneIDEnumerarion(UCAL_ZONE_TYPE_ANY, NULL, -5 hour)";
178             uenum = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, NULL, &offsetMinus5, &status);
179             break;
180         case 5:
181             api = "ucal_openTimeZoneIDEnumerarion(UCAL_ZONE_TYPE_ANY, US, -5 hour)";
182             uenum = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, "US", &offsetMinus5, &status);
183             break;
184         }
185         if (U_FAILURE(status)) {
186             log_err_status(status, "FAIL: %s failed with %s\n", api,
187                     u_errorName(status));
188         } else {
189             const char* id;
190             int32_t len;
191             count = uenum_count(uenum, &status);
192             log_verbose("%s returned %d timezone id's:\n", api, count);
193             if (count < 5) { /* Don't hard code an exact == test here! */
194                 log_data_err("FAIL: in %s, got %d, expected at least 5 -> %s (Are you missing data?)\n", api, count, u_errorName(status));
195             }
196             uenum_reset(uenum, &status);
197             if (U_FAILURE(status)){
198                 log_err("FAIL: uenum_reset for %s returned %s\n",
199                         api, u_errorName(status));
200             }
201             for (i=0; i<count; i++) {
202                 id = uenum_next(uenum, &len, &status);
203                 if (U_FAILURE(status)){
204                     log_err("FAIL: uenum_next for %s returned %s\n",
205                             api, u_errorName(status));
206                 } else {
207                     log_verbose("%s\n", id);
208                 }
209             }
210             /* Next one should be NULL */
211             id = uenum_next(uenum, &len, &status);
212             if (id != NULL) {
213                 log_err("FAIL: uenum_next for %s returned %s, expected NULL\n",
214                         api, id);
215             }
216         }
217         uenum_close(uenum);
218     }
219 
220     /*Test ucal_getDSTSavings*/
221     status = U_ZERO_ERROR;
222     i = ucal_getDSTSavings(fgGMTID, &status);
223     if (U_FAILURE(status)) {
224         log_err("FAIL: ucal_getDSTSavings(GMT) => %s\n",
225                 u_errorName(status));
226     } else if (i != 0) {
227         log_data_err("FAIL: ucal_getDSTSavings(GMT) => %d, expect 0 (Are you missing data?)\n", i);
228     }
229     i = ucal_getDSTSavings(PST, &status);
230     if (U_FAILURE(status)) {
231         log_err("FAIL: ucal_getDSTSavings(PST) => %s\n",
232                 u_errorName(status));
233     } else if (i != 1*60*60*1000) {
234         log_err("FAIL: ucal_getDSTSavings(PST) => %d, expect %d\n", i, 1*60*60*1000);
235     }
236 
237     /*Test ucal_set/getDefaultTimeZone and ucal_getHostTimeZone */
238     status = U_ZERO_ERROR;
239     i = ucal_getDefaultTimeZone(zone1, UPRV_LENGTHOF(zone1), &status);
240     if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) {
241         log_err("FAIL: ucal_getDefaultTimeZone() => %s\n",
242                 u_errorName(status));
243     } else {
244         ucal_setDefaultTimeZone(EUROPE_PARIS, &status);
245         if (U_FAILURE(status)) {
246             log_err("FAIL: ucal_setDefaultTimeZone(Europe/Paris) => %s\n",
247                     u_errorName(status));
248         } else {
249             i = ucal_getDefaultTimeZone(zone2, UPRV_LENGTHOF(zone2), &status);
250             if (U_FAILURE(status)) {
251                 log_err("FAIL: ucal_getDefaultTimeZone() => %s\n",
252                         u_errorName(status));
253             } else {
254                 if (u_strcmp(zone2, EUROPE_PARIS) != 0) {
255                     log_data_err("FAIL: ucal_getDefaultTimeZone() did not return Europe/Paris (Are you missing data?)\n");
256                 } else {
257                     // Redetect the host timezone, it should be the same as zone1 even though ICU's default timezone has been changed.
258                     i = ucal_getHostTimeZone(zone2, UPRV_LENGTHOF(zone2), &status);
259                     if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) {
260                         log_err("FAIL: ucal_getHostTimeZone() => %s\n", u_errorName(status));
261                     } else {
262                         if (u_strcmp(zone1, zone2) != 0) {
263                             log_err("FAIL: ucal_getHostTimeZone() should give the same host timezone even if the default changed. (Got '%s', Expected '%s').\n",
264                                 u_austrcpy(tempMsgBuf, zone2), u_austrcpy(tempMsgBuf2, zone1));
265                         }
266                     }
267                 }
268             }
269         }
270         status = U_ZERO_ERROR;
271         ucal_setDefaultTimeZone(zone1, &status);
272     }
273 
274     /*Test ucal_getTZDataVersion*/
275     status = U_ZERO_ERROR;
276     tzver = ucal_getTZDataVersion(&status);
277     if (U_FAILURE(status)) {
278         log_err_status(status, "FAIL: ucal_getTZDataVersion() => %s\n", u_errorName(status));
279     } else {
280         tzverLen = uprv_strlen(tzver);
281         if (tzverLen == 5 || tzverLen == 6 /* 4 digits + 1 or 2 letters */) {
282             log_verbose("PASS: ucal_getTZDataVersion returned %s\n", tzver);
283         } else {
284             log_err("FAIL: Bad version string was returned by ucal_getTZDataVersion\n");
285         }
286     }
287 
288     /*Testing ucal_getCanonicalTimeZoneID*/
289     status = U_ZERO_ERROR;
290     resultlength = ucal_getCanonicalTimeZoneID(PST, -1,
291         canonicalID, UPRV_LENGTHOF(canonicalID), &isSystemID, &status);
292     if (U_FAILURE(status)) {
293         log_data_err("FAIL: error in ucal_getCanonicalTimeZoneID : %s\n", u_errorName(status));
294     } else {
295         if (u_strcmp(AMERICA_LOS_ANGELES, canonicalID) != 0) {
296             log_data_err("FAIL: ucal_getCanonicalTimeZoneID(%s) returned %s : expected - %s (Are you missing data?)\n",
297                 PST, canonicalID, AMERICA_LOS_ANGELES);
298         }
299         if (!isSystemID) {
300             log_data_err("FAIL: ucal_getCanonicalTimeZoneID(%s) set %d to isSystemID (Are you missing data?)\n",
301                 PST, isSystemID);
302         }
303     }
304 
305     /*Testing the  ucal_open() function*/
306     status = U_ZERO_ERROR;
307     log_verbose("\nTesting the ucal_open()\n");
308     u_uastrcpy(tzID, "PST");
309     caldef=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
310     if(U_FAILURE(status)){
311         log_data_err("FAIL: error in ucal_open caldef : %s\n - (Are you missing data?)", u_errorName(status));
312     }
313 
314     caldef2=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
315     if(U_FAILURE(status)){
316         log_data_err("FAIL: error in ucal_open caldef : %s - (Are you missing data?)\n", u_errorName(status));
317     }
318     u_strcpy(tzID, fgGMTID);
319     calfr=ucal_open(tzID, u_strlen(tzID), "fr_FR", UCAL_TRADITIONAL, &status);
320     if(U_FAILURE(status)){
321         log_data_err("FAIL: error in ucal_open calfr : %s - (Are you missing data?)\n", u_errorName(status));
322     }
323     calit=ucal_open(tzID, u_strlen(tzID), "it_IT", UCAL_TRADITIONAL, &status);
324     if(U_FAILURE(status))    {
325         log_data_err("FAIL: error in ucal_open calit : %s - (Are you missing data?)\n", u_errorName(status));
326     }
327 
328     /*Testing the  clone() function*/
329     calfrclone = ucal_clone(calfr, &status);
330     if(U_FAILURE(status)){
331         log_data_err("FAIL: error in ucal_clone calfr : %s - (Are you missing data?)\n", u_errorName(status));
332     }
333 
334     /*Testing udat_getAvailable() and udat_countAvailable()*/
335     log_verbose("\nTesting getAvailableLocales and countAvailable()\n");
336     count=ucal_countAvailable();
337     /* use something sensible w/o hardcoding the count */
338     if(count > 0) {
339         log_verbose("PASS: ucal_countAvailable() works fine\n");
340         log_verbose("The no: of locales for which calendars are available are %d\n", count);
341     } else {
342         log_data_err("FAIL: Error in countAvailable()\n");
343     }
344 
345     for(i=0;i<count;i++) {
346        log_verbose("%s\n", ucal_getAvailable(i));
347     }
348 
349 
350     /*Testing the equality between calendar's*/
351     log_verbose("\nTesting ucal_equivalentTo()\n");
352     if(caldef && caldef2 && calfr && calit) {
353       if(ucal_equivalentTo(caldef, caldef2) == false || ucal_equivalentTo(caldef, calfr)== true ||
354         ucal_equivalentTo(caldef, calit)== true || ucal_equivalentTo(calfr, calfrclone) == false) {
355           log_data_err("FAIL: Error. equivalentTo test failed (Are you missing data?)\n");
356       } else {
357           log_verbose("PASS: equivalentTo test passed\n");
358       }
359     }
360 
361 
362     /*Testing the current time and date using ucal_getnow()*/
363     log_verbose("\nTesting the ucal_getNow function to check if it is fetching tbe current time\n");
364     now=ucal_getNow();
365     /* open the date format and format the date to check the output */
366     datdef=udat_open(UDAT_FULL,UDAT_FULL ,NULL, NULL, 0,NULL,0,&status);
367     if(U_FAILURE(status)){
368         log_data_err("FAIL: error in creating the dateformat : %s (Are you missing data?)\n", u_errorName(status));
369         ucal_close(caldef2);
370         ucal_close(calfr);
371         ucal_close(calit);
372         ucal_close(calfrclone);
373         ucal_close(caldef);
374         return;
375     }
376     log_verbose("PASS: The current date and time fetched is %s\n", u_austrcpy(tempMsgBuf, myDateFormat(datdef, now)) );
377 
378 
379     /*Testing the TimeZoneDisplayName */
380     log_verbose("\nTesting the fetching of time zone display name\n");
381     /*for the US locale */
382     resultlength=0;
383     resultlengthneeded=ucal_getTimeZoneDisplayName(caldef, UCAL_DST, "en_US", NULL, resultlength, &status);
384 
385     if(status==U_BUFFER_OVERFLOW_ERROR)
386     {
387         status=U_ZERO_ERROR;
388         resultlength=resultlengthneeded+1;
389         result=(UChar*)malloc(sizeof(UChar) * resultlength);
390         ucal_getTimeZoneDisplayName(caldef, UCAL_DST, "en_US", result, resultlength, &status);
391     }
392     if(U_FAILURE(status))    {
393         log_err("FAIL: Error in getting the timezone display name : %s\n", u_errorName(status));
394     }
395     else{
396         log_verbose("PASS: getting the time zone display name successful : %s, %d needed \n",
397             u_errorName(status), resultlengthneeded);
398     }
399 
400 
401 #define expectPDT "Pacific Daylight Time"
402 
403     tzdname=(UChar*)malloc(sizeof(UChar) * (sizeof(expectPDT)+1));
404     u_uastrcpy(tzdname, expectPDT);
405     if(u_strcmp(tzdname, result)==0){
406         log_verbose("PASS: got the correct time zone display name %s\n", u_austrcpy(tempMsgBuf, result) );
407     }
408     else{
409         log_err("FAIL: got the wrong time zone(DST) display name %s, wanted %s\n", austrdup(result) , expectPDT);
410     }
411 
412     ucal_getTimeZoneDisplayName(caldef, UCAL_SHORT_DST, "en_US", result, resultlength, &status);
413     u_uastrcpy(tzdname, "PDT");
414     if(u_strcmp(tzdname, result) != 0){
415         log_err("FAIL: got the wrong time zone(SHORT_DST) display name %s, wanted %s\n", austrdup(result), austrdup(tzdname));
416     }
417 
418     ucal_getTimeZoneDisplayName(caldef, UCAL_STANDARD, "en_US", result, resultlength, &status);
419     u_uastrcpy(tzdname, "Pacific Standard Time");
420     if(u_strcmp(tzdname, result) != 0){
421         log_err("FAIL: got the wrong time zone(STANDARD) display name %s, wanted %s\n", austrdup(result), austrdup(tzdname));
422     }
423 
424     ucal_getTimeZoneDisplayName(caldef, UCAL_SHORT_STANDARD, "en_US", result, resultlength, &status);
425     u_uastrcpy(tzdname, "PST");
426     if(u_strcmp(tzdname, result) != 0){
427         log_err("FAIL: got the wrong time zone(SHORT_STANDARD) display name %s, wanted %s\n", austrdup(result), austrdup(tzdname));
428     }
429 
430 
431     /*testing the setAttributes and getAttributes of a UCalendar*/
432     log_verbose("\nTesting the getAttributes and set Attributes\n");
433     count=ucal_getAttribute(calit, UCAL_LENIENT);
434     count2=ucal_getAttribute(calfr, UCAL_LENIENT);
435     ucal_setAttribute(calit, UCAL_LENIENT, 0);
436     ucal_setAttribute(caldef, UCAL_LENIENT, count2);
437     if( ucal_getAttribute(calit, UCAL_LENIENT) !=0 ||
438         ucal_getAttribute(calfr, UCAL_LENIENT)!=ucal_getAttribute(caldef, UCAL_LENIENT) )
439         log_err("FAIL: there is an error in getAttributes or setAttributes\n");
440     else
441         log_verbose("PASS: attribute set and got successfully\n");
442         /*set it back to original value */
443     log_verbose("Setting it back to normal\n");
444     ucal_setAttribute(calit, UCAL_LENIENT, count);
445     if(ucal_getAttribute(calit, UCAL_LENIENT)!=count)
446         log_err("FAIL: Error in setting the attribute back to normal\n");
447 
448     /*setting the first day of the week to other values  */
449     count=ucal_getAttribute(calit, UCAL_FIRST_DAY_OF_WEEK);
450     for (i=1; i<=7; ++i) {
451         ucal_setAttribute(calit, UCAL_FIRST_DAY_OF_WEEK,i);
452         if (ucal_getAttribute(calit, UCAL_FIRST_DAY_OF_WEEK) != i)
453             log_err("FAIL: set/getFirstDayOfWeek failed\n");
454     }
455     /*get bogus Attribute*/
456     count=ucal_getAttribute(calit, (UCalendarAttribute)99); /* BOGUS_ATTRIBUTE */
457     if(count != -1){
458         log_err("FAIL: get/bogus attribute should return -1\n");
459     }
460 
461     /*set it back to normal */
462     ucal_setAttribute(calit, UCAL_FIRST_DAY_OF_WEEK,count);
463     /*setting minimal days of the week to other values */
464     count=ucal_getAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK);
465     for (i=1; i<=7; ++i) {
466         ucal_setAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,i);
467         if (ucal_getAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK) != i)
468             log_err("FAIL: set/getMinimalDaysInFirstWeek failed\n");
469     }
470     /*set it back to normal */
471     ucal_setAttribute(calit, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,count);
472 
473 
474     /*testing if the UCalendar's timezone is currently in day light saving's time*/
475     log_verbose("\nTesting if the UCalendar is currently in daylight saving's time\n");
476     ucal_setDateTime(caldef, 1999, UCAL_MARCH, 3, 10, 45, 20, &status);
477     ucal_inDaylightTime(caldef, &status );
478     if(U_FAILURE(status))    {
479         log_err("Error in ucal_inDaylightTime: %s\n", u_errorName(status));
480     }
481     if(!ucal_inDaylightTime(caldef, &status))
482         log_verbose("PASS: It is not in daylight saving's time\n");
483     else
484         log_err("FAIL: It is not in daylight saving's time\n");
485 
486     /*closing the UCalendar*/
487     ucal_close(caldef);
488     ucal_close(caldef2);
489     ucal_close(calfr);
490     ucal_close(calit);
491     ucal_close(calfrclone);
492 
493     /*testing ucal_getType, and ucal_open with UCAL_GREGORIAN*/
494     for (ucalGetTypeTestPtr = ucalGetTypeTests; ucalGetTypeTestPtr->expectedResult != NULL; ++ucalGetTypeTestPtr) {
495         const char * localeToDisplay = (ucalGetTypeTestPtr->locale != NULL)? ucalGetTypeTestPtr->locale: "<NULL>";
496         status = U_ZERO_ERROR;
497         caldef = ucal_open(NULL, 0, ucalGetTypeTestPtr->locale, ucalGetTypeTestPtr->calType, &status);
498         if ( U_SUCCESS(status) ) {
499             const char * calType = ucal_getType(caldef, &status);
500             if ( U_SUCCESS(status) && calType != NULL ) {
501                 if ( uprv_strcmp( calType, ucalGetTypeTestPtr->expectedResult ) != 0 ) {
502                     log_err("FAIL: ucal_open %s type %d does not return %s calendar\n", localeToDisplay,
503                                                 ucalGetTypeTestPtr->calType, ucalGetTypeTestPtr->expectedResult);
504                 }
505             } else {
506                 log_err("FAIL: ucal_open %s type %d, then ucal_getType fails\n", localeToDisplay, ucalGetTypeTestPtr->calType);
507             }
508             ucal_close(caldef);
509         } else {
510             log_err("FAIL: ucal_open %s type %d fails\n", localeToDisplay, ucalGetTypeTestPtr->calType);
511         }
512     }
513 
514     /*closing the UDateFormat used */
515     udat_close(datdef);
516     free(result);
517     free(tzdname);
518 }
519 
520 /*------------------------------------------------------*/
521 /*Testing the getMillis, setMillis, setDate and setDateTime functions extensively*/
522 
TestGetSetDateAPI()523 static void TestGetSetDateAPI()
524 {
525     UCalendar *caldef = 0, *caldef2 = 0, *caldef3 = 0;
526     UChar tzID[4];
527     UDate d1;
528     int32_t hour;
529     int32_t zoneOffset;
530     UDateFormat *datdef = 0;
531     UErrorCode status=U_ZERO_ERROR;
532     UDate d2= 837039928046.0;
533     UChar temp[30];
534 	double testMillis;
535 	int32_t dateBit;
536     UChar id[4];
537     int32_t idLen;
538 
539     log_verbose("\nOpening the calendars()\n");
540     u_strcpy(tzID, fgGMTID);
541     /*open the calendars used */
542     caldef=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
543     caldef2=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
544     caldef3=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
545     /*open the dateformat */
546     /* this is supposed to open default date format, but later on it treats it like it is "en_US"
547        - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
548     /*datdef=udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL,fgGMTID,-1, &status);*/
549     datdef=udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US",fgGMTID,-1,NULL,0, &status);
550     if(U_FAILURE(status))
551     {
552         log_data_err("error in creating the dateformat : %s (Are you missing data?)\n", u_errorName(status));
553         ucal_close(caldef);
554         ucal_close(caldef2);
555         ucal_close(caldef3);
556         udat_close(datdef);
557         return;
558     }
559 
560     /*Testing getMillis and setMillis */
561     log_verbose("\nTesting the date and time fetched in millis for a calendar using getMillis\n");
562     d1=ucal_getMillis(caldef, &status);
563     if(U_FAILURE(status)){
564         log_err("Error in getMillis : %s\n", u_errorName(status));
565     }
566 
567     /*testing setMillis */
568     log_verbose("\nTesting the set date and time function using setMillis\n");
569     ucal_setMillis(caldef, d2, &status);
570     if(U_FAILURE(status)){
571         log_err("Error in setMillis : %s\n", u_errorName(status));
572     }
573 
574     /*testing if the calendar date is set properly or not  */
575     d1=ucal_getMillis(caldef, &status);
576     if(u_strcmp(myDateFormat(datdef, d1), myDateFormat(datdef, d2))!=0)
577         log_err("error in setMillis or getMillis\n");
578     /*-------------------*/
579 
580     /*testing large negative millis*/
581 	/*test a previously failed millis and beyond the lower bounds - ICU trac #9403 */
582 	// -184303902611600000.0         - just beyond lower bounds (#9403 sets U_ILLEGAL_ARGUMENT_ERROR in strict mode)
583 	// -46447814188001000.0	         - fixed by #9403
584 
585     log_verbose("\nTesting very large valid millis & invalid setMillis values (in both strict & lienent modes) detected\n");
586 
587 	testMillis = -46447814188001000.0;	// point where floorDivide in handleComputeFields failed as per #9403
588 	log_verbose("using value[%lf]\n", testMillis);
589     ucal_setAttribute(caldef3, UCAL_LENIENT, 0);
590     ucal_setMillis(caldef3, testMillis, &status);
591    	if(U_FAILURE(status)){
592    		log_err("Fail: setMillis incorrectly detected invalid value : for millis : %e : returned  : %s\n", testMillis, u_errorName(status));
593 		status = U_ZERO_ERROR;
594 	}
595 
596     log_verbose("\nTesting invalid setMillis values detected\n");
597 	testMillis = -184303902611600000.0;
598 	log_verbose("using value[%lf]\n", testMillis);
599     ucal_setAttribute(caldef3, UCAL_LENIENT, 1);
600    	ucal_setMillis(caldef3, testMillis, &status);
601    	if(U_FAILURE(status)){
602    		log_err("Fail: setMillis incorrectly detected invalid value : for millis : %e : returned  : %s\n", testMillis, u_errorName(status));
603 		status = U_ZERO_ERROR;
604    	} else {
605         dateBit = ucal_get(caldef2, UCAL_MILLISECOND, &status);
606         if(testMillis == dateBit)
607         {
608 		    log_err("Fail: error in setMillis, allowed invalid value %e : returns millisecond : %d", testMillis, dateBit);
609         } else {
610             log_verbose("Pass: setMillis correctly pinned min, returned : %d", dateBit);
611         }
612 	}
613 
614     log_verbose("\nTesting invalid setMillis values detected\n");
615 	testMillis = -184303902611600000.0;
616 	log_verbose("using value[%lf]\n", testMillis);
617     ucal_setAttribute(caldef3, UCAL_LENIENT, 0);
618    	ucal_setMillis(caldef3, testMillis, &status);
619    	if(U_FAILURE(status)){
620    		log_verbose("Pass: Illegal argument error as expected : for millis : %e : returned  : %s\n", testMillis, u_errorName(status));
621 		status = U_ZERO_ERROR;
622    	} else {
623 		dateBit = ucal_get(caldef3, UCAL_DAY_OF_MONTH, &status);
624 		log_err("Fail: error in setMillis, allowed invalid value %e : returns DayOfMonth : %d", testMillis, dateBit);
625 	}
626 	/*-------------------*/
627 
628 
629     ctest_setTimeZone(NULL, &status);
630 
631     /*testing ucal_setTimeZone() and ucal_getTimeZoneID function*/
632     log_verbose("\nTesting if the function ucal_setTimeZone() and ucal_getTimeZoneID work fine\n");
633     idLen = ucal_getTimeZoneID(caldef2, id, UPRV_LENGTHOF(id), &status);
634     (void)idLen;    /* Suppress set but not used warning. */
635     if (U_FAILURE(status)) {
636         log_err("Error in getTimeZoneID : %s\n", u_errorName(status));
637     } else if (u_strcmp(id, fgGMTID) != 0) {
638         log_err("FAIL: getTimeZoneID returns a wrong ID: actual=%d, expected=%s\n", austrdup(id), austrdup(fgGMTID));
639     } else {
640         log_verbose("PASS: getTimeZoneID works fine\n");
641     }
642 
643     ucal_setMillis(caldef2, d2, &status);
644     if(U_FAILURE(status)){
645         log_err("Error in getMillis : %s\n", u_errorName(status));
646     }
647     hour=ucal_get(caldef2, UCAL_HOUR_OF_DAY, &status);
648 
649     u_uastrcpy(tzID, "PST");
650     ucal_setTimeZone(caldef2,tzID, 3, &status);
651     if(U_FAILURE(status)){
652         log_err("Error in setting the time zone using ucal_setTimeZone(): %s\n", u_errorName(status));
653     }
654     else
655         log_verbose("ucal_setTimeZone worked fine\n");
656 
657     idLen = ucal_getTimeZoneID(caldef2, id, UPRV_LENGTHOF(id), &status);
658     if (U_FAILURE(status)) {
659         log_err("Error in getTimeZoneID : %s\n", u_errorName(status));
660     } else if (u_strcmp(id, tzID) != 0) {
661         log_err("FAIL: getTimeZoneID returns a wrong ID: actual=%d, expected=%s\n", austrdup(id), austrdup(tzID));
662     } else {
663         log_verbose("PASS: getTimeZoneID works fine\n");
664     }
665 
666     if(hour == ucal_get(caldef2, UCAL_HOUR_OF_DAY, &status))
667         log_err("FAIL: Error setting the time zone doesn't change the represented time\n");
668     else if((hour-8 + 1) != ucal_get(caldef2, UCAL_HOUR_OF_DAY, &status)) /*because it is not in daylight savings time */
669         log_err("FAIL: Error setTimeZone doesn't change the represented time correctly with 8 hour offset\n");
670     else
671         log_verbose("PASS: setTimeZone works fine\n");
672 
673     /*testing setTimeZone roundtrip */
674     log_verbose("\nTesting setTimeZone() roundtrip\n");
675     u_strcpy(tzID, fgGMTID);
676     ucal_setTimeZone(caldef2, tzID, 3, &status);
677     if(U_FAILURE(status)){
678         log_err("Error in setting the time zone using ucal_setTimeZone(): %s\n", u_errorName(status));
679     }
680     if(d2==ucal_getMillis(caldef2, &status))
681         log_verbose("PASS: setTimeZone roundtrip test passed\n");
682     else
683         log_err("FAIL: setTimeZone roundtrip test failed\n");
684 
685     zoneOffset = ucal_get(caldef2, UCAL_ZONE_OFFSET, &status);
686     if(U_FAILURE(status)){
687         log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone(): %s\n", u_errorName(status));
688     }
689     else if (zoneOffset != 0) {
690         log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone() offset=%d\n", zoneOffset);
691     }
692 
693     ucal_setTimeZone(caldef2, NULL, -1, &status);
694     if(U_FAILURE(status)){
695         log_err("Error in setting the time zone using ucal_setTimeZone(): %s\n", u_errorName(status));
696     }
697     if(ucal_getMillis(caldef2, &status))
698         log_verbose("PASS: setTimeZone roundtrip test passed\n");
699     else
700         log_err("FAIL: setTimeZone roundtrip test failed\n");
701 
702     zoneOffset = ucal_get(caldef2, UCAL_ZONE_OFFSET, &status);
703     if(U_FAILURE(status)){
704         log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone(): %s\n", u_errorName(status));
705     }
706     else if (zoneOffset != -28800000) {
707         log_err("Error in getting the time zone using ucal_get() after using ucal_setTimeZone() offset=%d\n", zoneOffset);
708     }
709 
710     ctest_resetTimeZone();
711 
712 /*----------------------------*     */
713 
714 
715 
716     /*Testing  if setDate works fine  */
717     log_verbose("\nTesting the ucal_setDate() function \n");
718     u_strcpy(temp, u"Dec 17, 1971, 11:05:28\u202FPM");
719     ucal_setDate(caldef,1971, UCAL_DECEMBER, 17, &status);
720     if(U_FAILURE(status)){
721         log_err("error in setting the calendar date : %s\n", u_errorName(status));
722     }
723     /*checking if the calendar date is set properly or not  */
724     d1=ucal_getMillis(caldef, &status);
725     if(u_strcmp(myDateFormat(datdef, d1), temp)==0)
726         log_verbose("PASS:setDate works fine\n");
727     else
728         log_err("FAIL:Error in setDate()\n");
729 
730 
731     /* Testing setDate Extensively with various input values */
732     log_verbose("\nTesting ucal_setDate() extensively\n");
733     ucal_setDate(caldef, 1999, UCAL_JANUARY, 10, &status);
734     verify1("1999  10th day of January  is :", caldef, datdef, 1999, UCAL_JANUARY, 10);
735     ucal_setDate(caldef, 1999, UCAL_DECEMBER, 3, &status);
736     verify1("1999 3rd day of December  is :", caldef, datdef, 1999, UCAL_DECEMBER, 3);
737     ucal_setDate(caldef, 2000, UCAL_MAY, 3, &status);
738     verify1("2000 3rd day of May is :", caldef, datdef, 2000, UCAL_MAY, 3);
739     ucal_setDate(caldef, 1999, UCAL_AUGUST, 32, &status);
740     verify1("1999 32th day of August is :", caldef, datdef, 1999, UCAL_SEPTEMBER, 1);
741     ucal_setDate(caldef, 1999, UCAL_MARCH, 0, &status);
742     verify1("1999 0th day of March is :", caldef, datdef, 1999, UCAL_FEBRUARY, 28);
743     ucal_setDate(caldef, 0, UCAL_MARCH, 12, &status);
744 
745     /*--------------------*/
746 
747     /*Testing if setDateTime works fine */
748     log_verbose("\nTesting the ucal_setDateTime() function \n");
749     u_strcpy(temp, u"May 3, 1972, 4:30:42\u202FPM");
750     ucal_setDateTime(caldef,1972, UCAL_MAY, 3, 16, 30, 42, &status);
751     if(U_FAILURE(status)){
752         log_err("error in setting the calendar date : %s\n", u_errorName(status));
753     }
754     /*checking  if the calendar date is set properly or not  */
755     d1=ucal_getMillis(caldef, &status);
756     if(u_strcmp(myDateFormat(datdef, d1), temp)==0)
757         log_verbose("PASS: setDateTime works fine\n");
758     else
759         log_err("FAIL: Error in setDateTime\n");
760 
761 
762 
763     /*Testing setDateTime extensively with various input values*/
764     log_verbose("\nTesting ucal_setDateTime() function extensively\n");
765     ucal_setDateTime(caldef, 1999, UCAL_OCTOBER, 10, 6, 45, 30, &status);
766     verify2("1999  10th day of October  at 6:45:30 is :", caldef, datdef, 1999, UCAL_OCTOBER, 10, 6, 45, 30, 0 );
767     ucal_setDateTime(caldef, 1999, UCAL_MARCH, 3, 15, 10, 55, &status);
768     verify2("1999 3rd day of March   at 15:10:55 is :", caldef, datdef, 1999, UCAL_MARCH, 3, 3, 10, 55, 1);
769     ucal_setDateTime(caldef, 1999, UCAL_MAY, 3, 25, 30, 45, &status);
770     verify2("1999 3rd day of May at 25:30:45 is :", caldef, datdef, 1999, UCAL_MAY, 4, 1, 30, 45, 0);
771     ucal_setDateTime(caldef, 1999, UCAL_AUGUST, 32, 22, 65, 40, &status);
772     verify2("1999 32th day of August at 22:65:40 is :", caldef, datdef, 1999, UCAL_SEPTEMBER, 1, 11, 5, 40,1);
773     ucal_setDateTime(caldef, 1999, UCAL_MARCH, 12, 0, 0, 0,&status);
774     verify2("1999 12th day of March at 0:0:0 is :", caldef, datdef, 1999, UCAL_MARCH, 12, 0, 0, 0, 0);
775     ucal_setDateTime(caldef, 1999, UCAL_MARCH, 12, -10, -10,0, &status);
776     verify2("1999 12th day of March is at -10:-10:0 :", caldef, datdef, 1999, UCAL_MARCH, 11, 1, 50, 0, 1);
777 
778 
779 
780     /*close caldef and datdef*/
781     ucal_close(caldef);
782     ucal_close(caldef2);
783     ucal_close(caldef3);
784     udat_close(datdef);
785 }
786 
787 /*----------------------------------------------------------- */
788 /**
789  * Confirm the functioning of the calendar field related functions.
790  */
TestFieldGetSet()791 static void TestFieldGetSet()
792 {
793     UCalendar *cal = 0;
794     UChar tzID[4];
795     UDateFormat *datdef = 0;
796     UDate d1 = 0;
797     UErrorCode status=U_ZERO_ERROR;
798     (void)d1;   /* Suppress set but not used warning. */
799     log_verbose("\nFetching pointer to UCalendar using the ucal_open()\n");
800     u_strcpy(tzID, fgGMTID);
801     /*open the calendar used */
802     cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
803     if (U_FAILURE(status)) {
804         log_data_err("ucal_open failed: %s - (Are you missing data?)\n", u_errorName(status));
805         return;
806     }
807     datdef=udat_open(UDAT_SHORT,UDAT_SHORT ,NULL,fgGMTID,-1,NULL, 0, &status);
808     if(U_FAILURE(status))
809     {
810         log_data_err("error in creating the dateformat : %s (Are you missing data?)\n", u_errorName(status));
811     }
812 
813     /*Testing ucal_get()*/
814     log_verbose("\nTesting the ucal_get() function of Calendar\n");
815     ucal_setDateTime(cal, 1999, UCAL_MARCH, 12, 5, 25, 30, &status);
816     if(U_FAILURE(status)){
817         log_data_err("error in the setDateTime() : %s (Are you missing data?)\n", u_errorName(status));
818     }
819     if(ucal_get(cal, UCAL_YEAR, &status)!=1999 || ucal_get(cal, UCAL_MONTH, &status)!=2 ||
820         ucal_get(cal, UCAL_DATE, &status)!=12 || ucal_get(cal, UCAL_HOUR, &status)!=5)
821         log_data_err("error in ucal_get() -> %s (Are you missing data?)\n", u_errorName(status));
822     else if(ucal_get(cal, UCAL_DAY_OF_WEEK_IN_MONTH, &status)!=2 || ucal_get(cal, UCAL_DAY_OF_WEEK, &status)!=6
823         || ucal_get(cal, UCAL_WEEK_OF_MONTH, &status)!=2 || ucal_get(cal, UCAL_WEEK_OF_YEAR, &status)!= 11)
824         log_err("FAIL: error in ucal_get()\n");
825     else
826         log_verbose("PASS: ucal_get() works fine\n");
827 
828     /*Testing the ucal_set() , ucal_clear() functions of calendar*/
829     log_verbose("\nTesting the set, and clear  field functions of calendar\n");
830     ucal_setAttribute(cal, UCAL_LENIENT, 0);
831     ucal_clear(cal);
832     ucal_set(cal, UCAL_YEAR, 1997);
833     ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
834     ucal_set(cal, UCAL_DATE, 3);
835     verify1("1997 third day of June = ", cal, datdef, 1997, UCAL_JUNE, 3);
836     ucal_clear(cal);
837     ucal_set(cal, UCAL_YEAR, 1997);
838     ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
839     ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
840     ucal_set(cal, UCAL_DAY_OF_WEEK_IN_MONTH, 1);
841     verify1("1997 first Tuesday in June = ", cal, datdef, 1997, UCAL_JUNE, 3);
842     ucal_clear(cal);
843     ucal_set(cal, UCAL_YEAR, 1997);
844     ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
845     ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
846     ucal_set(cal, UCAL_DAY_OF_WEEK_IN_MONTH, - 1);
847     verify1("1997 last Tuesday in June = ", cal, datdef,1997,   UCAL_JUNE, 24);
848     /*give undesirable input    */
849     status = U_ZERO_ERROR;
850     ucal_clear(cal);
851     ucal_set(cal, UCAL_YEAR, 1997);
852     ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
853     ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
854     ucal_set(cal, UCAL_DAY_OF_WEEK_IN_MONTH, 0);
855     d1 = ucal_getMillis(cal, &status);
856     if (status != U_ILLEGAL_ARGUMENT_ERROR) {
857         log_err("FAIL: U_ILLEGAL_ARGUMENT_ERROR was not returned for : 1997 zero-th Tuesday in June\n");
858     } else {
859         log_verbose("PASS: U_ILLEGAL_ARGUMENT_ERROR as expected\n");
860     }
861     status = U_ZERO_ERROR;
862     ucal_clear(cal);
863     ucal_set(cal, UCAL_YEAR, 1997);
864     ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
865     ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
866     ucal_set(cal, UCAL_WEEK_OF_MONTH, 1);
867     verify1("1997 Tuesday in week 1 of June = ", cal,datdef, 1997, UCAL_JUNE, 3);
868     ucal_clear(cal);
869     ucal_set(cal, UCAL_YEAR, 1997);
870     ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
871     ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
872     ucal_set(cal, UCAL_WEEK_OF_MONTH, 5);
873     verify1("1997 Tuesday in week 5 of June = ", cal,datdef, 1997, UCAL_JULY, 1);
874     status = U_ZERO_ERROR;
875     ucal_clear(cal);
876     ucal_set(cal, UCAL_YEAR, 1997);
877     ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
878     ucal_set(cal, UCAL_MONTH, UCAL_JUNE);
879     ucal_set(cal, UCAL_WEEK_OF_MONTH, 0);
880     ucal_setAttribute(cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,1);
881     d1 = ucal_getMillis(cal,&status);
882     if (status != U_ILLEGAL_ARGUMENT_ERROR){
883         log_err("FAIL: U_ILLEGAL_ARGUMENT_ERROR was not returned for : 1997 Tuesday zero-th week in June\n");
884     } else {
885         log_verbose("PASS: U_ILLEGAL_ARGUMENT_ERROR as expected\n");
886     }
887     status = U_ZERO_ERROR;
888     ucal_clear(cal);
889     ucal_set(cal, UCAL_YEAR_WOY, 1997);
890     ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
891     ucal_set(cal, UCAL_WEEK_OF_YEAR, 1);
892     verify1("1997 Tuesday in week 1 of year = ", cal, datdef,1996, UCAL_DECEMBER, 31);
893     ucal_clear(cal);
894     ucal_set(cal, UCAL_YEAR, 1997);
895     ucal_set(cal, UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
896     ucal_set(cal, UCAL_WEEK_OF_YEAR, 10);
897     verify1("1997 Tuesday in week 10 of year = ", cal,datdef, 1997, UCAL_MARCH, 4);
898     ucal_clear(cal);
899     ucal_set(cal, UCAL_YEAR, 1999);
900     ucal_set(cal, UCAL_DAY_OF_YEAR, 1);
901     verify1("1999 1st day of the year =", cal, datdef, 1999, UCAL_JANUARY, 1);
902     ucal_set(cal, UCAL_MONTH, -3);
903     d1 = ucal_getMillis(cal,&status);
904     if (status != U_ILLEGAL_ARGUMENT_ERROR){
905         log_err("FAIL: U_ILLEGAL_ARGUMENT_ERROR was not returned for : 1999 -3th month\n");
906     } else {
907         log_verbose("PASS: U_ILLEGAL_ARGUMENT_ERROR as expected\n");
908     }
909 
910     ucal_setAttribute(cal, UCAL_LENIENT, 1);
911 
912     ucal_set(cal, UCAL_MONTH, -3);
913     verify1("1999 -3th month should be", cal, datdef, 1998, UCAL_OCTOBER, 1);
914 
915 
916     /*testing isSet and clearField()*/
917     if(!ucal_isSet(cal, UCAL_WEEK_OF_YEAR))
918         log_err("FAIL: error in isSet\n");
919     else
920         log_verbose("PASS: isSet working fine\n");
921     ucal_clearField(cal, UCAL_WEEK_OF_YEAR);
922     if(ucal_isSet(cal, UCAL_WEEK_OF_YEAR))
923         log_err("FAIL: there is an error in clearField or isSet\n");
924     else
925         log_verbose("PASS :clearField working fine\n");
926 
927     /*-------------------------------*/
928 
929     ucal_close(cal);
930     udat_close(datdef);
931 }
932 
933 typedef struct {
934     const char * zone;
935     int32_t      year;
936     int32_t      month;
937     int32_t      day;
938     int32_t      hour;
939 } TransitionItem;
940 
941 static const TransitionItem transitionItems[] = {
942     { "America/Caracas", 2007, UCAL_DECEMBER,  8, 10 }, /* day before change in UCAL_ZONE_OFFSET */
943     { "US/Pacific",      2011,    UCAL_MARCH, 12, 10 }, /* day before change in UCAL_DST_OFFSET */
944     { NULL,                 0,             0,  0,  0 }
945 };
946 
947 /* ------------------------------------- */
948 /**
949  * Execute adding and rolling in Calendar extensively,
950  */
TestAddRollExtensive()951 static void TestAddRollExtensive()
952 {
953     const TransitionItem * itemPtr;
954     UCalendar *cal = 0;
955     int32_t i,limit;
956     UChar tzID[32];
957     UCalendarDateFields e;
958     int32_t y,m,d,hr,min,sec,ms;
959     int32_t maxlimit = 40;
960     UErrorCode status = U_ZERO_ERROR;
961     y = 1997; m = UCAL_FEBRUARY; d = 1; hr = 1; min = 1; sec = 0; ms = 0;
962 
963     log_verbose("Testing add and roll extensively\n");
964 
965     u_uastrcpy(tzID, "PST");
966     /*open the calendar used */
967     cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);
968     if (U_FAILURE(status)) {
969         log_data_err("ucal_open() failed : %s - (Are you missing data?)\n", u_errorName(status));
970         return;
971     }
972 
973     ucal_set(cal, UCAL_YEAR, y);
974     ucal_set(cal, UCAL_MONTH, m);
975     ucal_set(cal, UCAL_DATE, d);
976     ucal_setAttribute(cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,1);
977 
978     /* Confirm that adding to various fields works.*/
979     log_verbose("\nTesting to confirm that adding to various fields works with ucal_add()\n");
980     checkDate(cal, y, m, d);
981     ucal_add(cal,UCAL_YEAR, 1, &status);
982     if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status)); return; }
983     y++;
984     checkDate(cal, y, m, d);
985     ucal_add(cal,UCAL_MONTH, 12, &status);
986     if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; }
987     y+=1;
988     checkDate(cal, y, m, d);
989     ucal_add(cal,UCAL_DATE, 1, &status);
990     if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; }
991     d++;
992     checkDate(cal, y, m, d);
993     ucal_add(cal,UCAL_DATE, 2, &status);
994     if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; }
995     d += 2;
996     checkDate(cal, y, m, d);
997     ucal_add(cal,UCAL_DATE, 28, &status);
998     if (U_FAILURE(status)) { log_err("ucal_add failed: %s\n", u_errorName(status) ); return; }
999     ++m;
1000     checkDate(cal, y, m, d);
1001     ucal_add(cal, (UCalendarDateFields)-1, 10, &status);
1002     if(status==U_ILLEGAL_ARGUMENT_ERROR)
1003         log_verbose("Pass: Illegal argument error as expected\n");
1004     else{
1005         log_err("Fail: No, illegal argument error as expected. Got....: %s\n", u_errorName(status));
1006     }
1007     status=U_ZERO_ERROR;
1008 
1009 
1010     /*confirm that applying roll to various fields works fine*/
1011     log_verbose("\nTesting to confirm that ucal_roll() works\n");
1012     ucal_roll(cal, UCAL_DATE, -1, &status);
1013     if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
1014     d -=1;
1015     checkDate(cal, y, m, d);
1016     ucal_roll(cal, UCAL_MONTH, -2, &status);
1017     if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
1018     m -=2;
1019     checkDate(cal, y, m, d);
1020     ucal_roll(cal, UCAL_DATE, 1, &status);
1021     if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
1022     d +=1;
1023     checkDate(cal, y, m, d);
1024     ucal_roll(cal, UCAL_MONTH, -12, &status);
1025     if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
1026     checkDate(cal, y, m, d);
1027     ucal_roll(cal, UCAL_YEAR, -1, &status);
1028     if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
1029     y -=1;
1030     checkDate(cal, y, m, d);
1031     ucal_roll(cal, UCAL_DATE, 29, &status);
1032     if (U_FAILURE(status)) { log_err("ucal_roll failed: %s\n", u_errorName(status) ); return; }
1033     d = 2;
1034     checkDate(cal, y, m, d);
1035     ucal_roll(cal, (UCalendarDateFields)-1, 10, &status);
1036     if(status==U_ILLEGAL_ARGUMENT_ERROR)
1037         log_verbose("Pass: illegal argument error as expected\n");
1038     else{
1039         log_err("Fail: no illegal argument error got..: %s\n", u_errorName(status));
1040         return;
1041     }
1042     status=U_ZERO_ERROR;
1043     ucal_clear(cal);
1044     ucal_setDateTime(cal, 1999, UCAL_FEBRUARY, 28, 10, 30, 45,  &status);
1045     if(U_FAILURE(status)){
1046         log_err("error is setting the datetime: %s\n", u_errorName(status));
1047     }
1048     ucal_add(cal, UCAL_MONTH, 1, &status);
1049     checkDate(cal, 1999, UCAL_MARCH, 28);
1050     ucal_add(cal, UCAL_MILLISECOND, 1000, &status);
1051     checkDateTime(cal, 1999, UCAL_MARCH, 28, 10, 30, 46, 0, UCAL_MILLISECOND);
1052 
1053     ucal_close(cal);
1054 /*--------------- */
1055     status=U_ZERO_ERROR;
1056     /* Testing add and roll extensively */
1057     log_verbose("\nTesting the ucal_add() and ucal_roll() functions extensively\n");
1058     y = 1997; m = UCAL_FEBRUARY; d = 1; hr = 1; min = 1; sec = 0; ms = 0;
1059     cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
1060     if (U_FAILURE(status)) {
1061         log_err("ucal_open failed: %s\n", u_errorName(status));
1062         return;
1063     }
1064     ucal_set(cal, UCAL_YEAR, y);
1065     ucal_set(cal, UCAL_MONTH, m);
1066     ucal_set(cal, UCAL_DATE, d);
1067     ucal_set(cal, UCAL_HOUR, hr);
1068     ucal_set(cal, UCAL_MINUTE, min);
1069     ucal_set(cal, UCAL_SECOND,sec);
1070     ucal_set(cal, UCAL_MILLISECOND, ms);
1071     ucal_setAttribute(cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,1);
1072     status=U_ZERO_ERROR;
1073 
1074     log_verbose("\nTesting UCalendar add...\n");
1075     for(e = UCAL_YEAR;e < UCAL_FIELD_COUNT; e=(UCalendarDateFields)((int32_t)e + 1)) {
1076         limit = maxlimit;
1077         status = U_ZERO_ERROR;
1078         for (i = 0; i < limit; i++) {
1079             ucal_add(cal, e, 1, &status);
1080             if (U_FAILURE(status)) { limit = i; status = U_ZERO_ERROR; }
1081         }
1082         for (i = 0; i < limit; i++) {
1083             ucal_add(cal, e, -1, &status);
1084             if (U_FAILURE(status)) {
1085                 log_err("ucal_add -1 failed: %s\n", u_errorName(status));
1086                 return;
1087             }
1088         }
1089         checkDateTime(cal, y, m, d, hr, min, sec, ms, e);
1090     }
1091     log_verbose("\nTesting calendar ucal_roll()...\n");
1092     for(e = UCAL_YEAR;e < UCAL_FIELD_COUNT; e=(UCalendarDateFields)((int32_t)e + 1)) {
1093         limit = maxlimit;
1094         status = U_ZERO_ERROR;
1095         for (i = 0; i < limit; i++) {
1096             ucal_roll(cal, e, 1, &status);
1097             if (U_FAILURE(status)) {
1098                 limit = i;
1099                 status = U_ZERO_ERROR;
1100             }
1101         }
1102         for (i = 0; i < limit; i++) {
1103             ucal_roll(cal, e, -1, &status);
1104             if (U_FAILURE(status)) {
1105                 log_err("ucal_roll -1 failed: %s\n", u_errorName(status));
1106                 return;
1107             }
1108         }
1109         checkDateTime(cal, y, m, d, hr, min, sec, ms, e);
1110     }
1111 
1112     ucal_close(cal);
1113 /*--------------- */
1114     log_verbose("\nTesting ucal_add() across ZONE_OFFSET and DST_OFFSE transitions.\n");
1115     for (itemPtr = transitionItems; itemPtr->zone != NULL; itemPtr++) {
1116         status=U_ZERO_ERROR;
1117         u_uastrcpy(tzID, itemPtr->zone);
1118         cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);
1119         if (U_FAILURE(status)) {
1120             log_err("ucal_open failed for zone %s: %s\n", itemPtr->zone, u_errorName(status));
1121             continue;
1122         }
1123         ucal_setDateTime(cal, itemPtr->year, itemPtr->month, itemPtr->day, itemPtr->hour, 0, 0, &status);
1124         ucal_add(cal, UCAL_DATE, 1, &status);
1125         hr = ucal_get(cal, UCAL_HOUR_OF_DAY, &status);
1126         if ( U_FAILURE(status) ) {
1127             log_err("ucal_add failed adding day across transition for zone %s: %s\n", itemPtr->zone, u_errorName(status));
1128         } else if ( hr != itemPtr->hour ) {
1129             log_err("ucal_add produced wrong hour %d when adding day across transition for zone %s\n", hr, itemPtr->zone);
1130         } else {
1131             ucal_add(cal, UCAL_DATE, -1, &status);
1132             hr = ucal_get(cal, UCAL_HOUR_OF_DAY, &status);
1133             if ( U_FAILURE(status) ) {
1134                 log_err("ucal_add failed subtracting day across transition for zone %s: %s\n", itemPtr->zone, u_errorName(status));
1135             } else if ( hr != itemPtr->hour ) {
1136                 log_err("ucal_add produced wrong hour %d when subtracting day across transition for zone %s\n", hr, itemPtr->zone);
1137             }
1138         }
1139         ucal_close(cal);
1140     }
1141 }
1142 
1143 /*------------------------------------------------------ */
1144 /*Testing the Limits for various Fields of Calendar*/
TestGetLimits()1145 static void TestGetLimits()
1146 {
1147     UCalendar *cal = 0;
1148     int32_t min, max, gr_min, le_max, ac_min, ac_max, val;
1149     UChar tzID[4];
1150     UErrorCode status = U_ZERO_ERROR;
1151 
1152 
1153     u_uastrcpy(tzID, "PST");
1154     /*open the calendar used */
1155     cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_GREGORIAN, &status);
1156     if (U_FAILURE(status)) {
1157         log_data_err("ucal_open() for gregorian calendar failed in TestGetLimits: %s - (Are you missing data?)\n", u_errorName(status));
1158         return;
1159     }
1160 
1161     log_verbose("\nTesting the getLimits function for various fields\n");
1162 
1163 
1164 
1165     ucal_setDate(cal, 1999, UCAL_MARCH, 5, &status); /* Set the date to be March 5, 1999 */
1166     val = ucal_get(cal, UCAL_DAY_OF_WEEK, &status);
1167     min = ucal_getLimit(cal, UCAL_DAY_OF_WEEK, UCAL_MINIMUM, &status);
1168     max = ucal_getLimit(cal, UCAL_DAY_OF_WEEK, UCAL_MAXIMUM, &status);
1169     if ( (min != UCAL_SUNDAY || max != UCAL_SATURDAY ) && (min > val && val > max)  && (val != UCAL_FRIDAY)){
1170            log_err("FAIL: Min/max bad\n");
1171            log_err("FAIL: Day of week %d out of range\n", val);
1172            log_err("FAIL: FAIL: Day of week should be SUNDAY Got %d\n", val);
1173     }
1174     else
1175         log_verbose("getLimits successful\n");
1176 
1177     val = ucal_get(cal, UCAL_DAY_OF_WEEK_IN_MONTH, &status);
1178     min = ucal_getLimit(cal, UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_MINIMUM, &status);
1179     max = ucal_getLimit(cal, UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_MAXIMUM, &status);
1180     if ( (min != 0 || max != 5 ) && (min > val && val > max)  && (val != 1)){
1181            log_err("FAIL: Min/max bad\n");
1182            log_err("FAIL: Day of week in month %d out of range\n", val);
1183            log_err("FAIL: FAIL: Day of week in month should be SUNDAY Got %d\n", val);
1184 
1185     }
1186     else
1187         log_verbose("getLimits successful\n");
1188 
1189     min=ucal_getLimit(cal, UCAL_MONTH, UCAL_MINIMUM, &status);
1190     max=ucal_getLimit(cal, UCAL_MONTH, UCAL_MAXIMUM, &status);
1191     gr_min=ucal_getLimit(cal, UCAL_MONTH, UCAL_GREATEST_MINIMUM, &status);
1192     le_max=ucal_getLimit(cal, UCAL_MONTH, UCAL_LEAST_MAXIMUM, &status);
1193     ac_min=ucal_getLimit(cal, UCAL_MONTH, UCAL_ACTUAL_MINIMUM, &status);
1194     ac_max=ucal_getLimit(cal, UCAL_MONTH, UCAL_ACTUAL_MAXIMUM, &status);
1195     if(U_FAILURE(status)){
1196         log_err("Error in getLimits: %s\n", u_errorName(status));
1197     }
1198     if(min!=0 || max!=11 || gr_min!=0 || le_max!=11 || ac_min!=0 || ac_max!=11)
1199         log_err("There is and error in getLimits in fetching the values\n");
1200     else
1201         log_verbose("getLimits successful\n");
1202 
1203     ucal_setDateTime(cal, 1999, UCAL_MARCH, 5, 4, 10, 35, &status);
1204     val=ucal_get(cal, UCAL_HOUR_OF_DAY, &status);
1205     min=ucal_getLimit(cal, UCAL_HOUR_OF_DAY, UCAL_MINIMUM, &status);
1206     max=ucal_getLimit(cal, UCAL_HOUR_OF_DAY, UCAL_MAXIMUM, &status);
1207     gr_min=ucal_getLimit(cal, UCAL_MINUTE, UCAL_GREATEST_MINIMUM, &status);
1208     le_max=ucal_getLimit(cal, UCAL_MINUTE, UCAL_LEAST_MAXIMUM, &status);
1209     ac_min=ucal_getLimit(cal, UCAL_MINUTE, UCAL_ACTUAL_MINIMUM, &status);
1210     ac_max=ucal_getLimit(cal, UCAL_SECOND, UCAL_ACTUAL_MAXIMUM, &status);
1211     if( (min!=0 || max!= 11 || gr_min!=0 || le_max!=60 || ac_min!=0 || ac_max!=60) &&
1212         (min>val && val>max) && val!=4){
1213 
1214         log_err("FAIL: Min/max bad\n");
1215         log_err("FAIL: Hour of Day %d out of range\n", val);
1216         log_err("FAIL: HOUR_OF_DAY should be 4 Got %d\n", val);
1217     }
1218     else
1219         log_verbose("getLimits successful\n");
1220 
1221 
1222     /*get BOGUS_LIMIT type*/
1223     val=ucal_getLimit(cal, UCAL_SECOND, (UCalendarLimitType)99, &status);
1224     if(val != -1){
1225         log_err("FAIL: ucal_getLimit() with BOGUS type should return -1\n");
1226     }
1227     status=U_ZERO_ERROR;
1228 
1229 
1230     ucal_close(cal);
1231 }
1232 
1233 
1234 
1235 /* ------------------------------------- */
1236 
1237 /**
1238  * Test that the days of the week progress properly when add is called repeatedly
1239  * for increments of 24 days.
1240  */
TestDOWProgression()1241 static void TestDOWProgression()
1242 {
1243     int32_t initialDOW, DOW, newDOW, expectedDOW;
1244     UCalendar *cal = 0;
1245     UDateFormat *datfor = 0;
1246     UDate date1;
1247     int32_t delta=24;
1248     UErrorCode status = U_ZERO_ERROR;
1249     UChar tzID[4];
1250     char tempMsgBuf[256];
1251     u_strcpy(tzID, fgGMTID);
1252     /*open the calendar used */
1253     cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
1254     if (U_FAILURE(status)) {
1255         log_data_err("ucal_open failed: %s - (Are you missing data?)\n", u_errorName(status));
1256         return;
1257     }
1258 
1259     datfor=udat_open(UDAT_MEDIUM,UDAT_MEDIUM ,NULL, fgGMTID,-1,NULL, 0, &status);
1260     if(U_FAILURE(status)){
1261         log_data_err("error in creating the dateformat : %s (Are you missing data?)\n", u_errorName(status));
1262     }
1263 
1264 
1265     ucal_setDate(cal, 1999, UCAL_JANUARY, 1, &status);
1266 
1267     log_verbose("\nTesting the DOW progression\n");
1268 
1269     initialDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status);
1270     if (U_FAILURE(status)) {
1271         log_data_err("ucal_get() failed: %s (Are you missing data?)\n", u_errorName(status) );
1272     } else {
1273         newDOW = initialDOW;
1274         do {
1275             DOW = newDOW;
1276             log_verbose("DOW = %d...\n", DOW);
1277             date1=ucal_getMillis(cal, &status);
1278             if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); break;}
1279             log_verbose("%s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)));
1280 
1281             ucal_add(cal,UCAL_DAY_OF_WEEK, delta, &status);
1282             if (U_FAILURE(status)) { log_err("ucal_add() failed: %s\n", u_errorName(status)); break; }
1283 
1284             newDOW = ucal_get(cal, UCAL_DAY_OF_WEEK, &status);
1285             if (U_FAILURE(status)) { log_err("ucal_get() failed: %s\n", u_errorName(status)); break; }
1286             expectedDOW = 1 + (DOW + delta - 1) % 7;
1287             date1=ucal_getMillis(cal, &status);
1288             if(U_FAILURE(status)){ log_err("ucal_getMiilis() failed: %s\n", u_errorName(status)); break;}
1289             if (newDOW != expectedDOW) {
1290                 log_err("Day of week should be %d instead of %d on %s", expectedDOW, newDOW,
1291                         u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) );
1292                 break;
1293             }
1294         }
1295         while (newDOW != initialDOW);
1296     }
1297 
1298     ucal_close(cal);
1299     udat_close(datfor);
1300 }
1301 
1302 /* ------------------------------------- */
1303 
1304 /**
1305  * Confirm that the offset between local time and GMT behaves as expected.
1306  */
TestGMTvsLocal()1307 static void TestGMTvsLocal()
1308 {
1309     log_verbose("\nTesting the offset between the GMT and local time\n");
1310     testZones(1999, 1, 1, 12, 0, 0);
1311     testZones(1999, 4, 16, 18, 30, 0);
1312     testZones(1998, 12, 17, 19, 0, 0);
1313 }
1314 
1315 /* ------------------------------------- */
1316 
testZones(int32_t yr,int32_t mo,int32_t dt,int32_t hr,int32_t mn,int32_t sc)1317 static void testZones(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn, int32_t sc)
1318 {
1319     int32_t offset,utc, expected;
1320     UCalendar *gmtcal = 0, *cal = 0;
1321     UDate date1;
1322     double temp;
1323     UDateFormat *datfor = 0;
1324     UErrorCode status = U_ZERO_ERROR;
1325     UChar tzID[4];
1326     char tempMsgBuf[256];
1327 
1328     u_strcpy(tzID, fgGMTID);
1329     gmtcal=ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status);
1330     if (U_FAILURE(status)) {
1331         log_data_err("ucal_open failed: %s - (Are you missing data?)\n", u_errorName(status));
1332         goto cleanup;
1333     }
1334     u_uastrcpy(tzID, "PST");
1335     cal = ucal_open(tzID, 3, "en_US", UCAL_TRADITIONAL, &status);
1336     if (U_FAILURE(status)) {
1337         log_err("ucal_open failed: %s\n", u_errorName(status));
1338         goto cleanup;
1339     }
1340 
1341     datfor=udat_open(UDAT_MEDIUM,UDAT_MEDIUM ,NULL, fgGMTID,-1,NULL, 0, &status);
1342     if(U_FAILURE(status)){
1343         log_data_err("error in creating the dateformat : %s (Are you missing data?)\n", u_errorName(status));
1344     }
1345 
1346     ucal_setDateTime(gmtcal, yr, mo - 1, dt, hr, mn, sc, &status);
1347     if (U_FAILURE(status)) {
1348         log_data_err("ucal_setDateTime failed: %s (Are you missing data?)\n", u_errorName(status));
1349         goto cleanup;
1350     }
1351     ucal_set(gmtcal, UCAL_MILLISECOND, 0);
1352     date1 = ucal_getMillis(gmtcal, &status);
1353     if (U_FAILURE(status)) {
1354         log_err("ucal_getMillis failed: %s\n", u_errorName(status));
1355         goto cleanup;
1356     }
1357     log_verbose("date = %s\n", u_austrcpy(tempMsgBuf, myDateFormat(datfor, date1)) );
1358 
1359 
1360     ucal_setMillis(cal, date1, &status);
1361     if (U_FAILURE(status)) {
1362         log_err("ucal_setMillis() failed: %s\n", u_errorName(status));
1363         goto cleanup;
1364     }
1365 
1366     offset = ucal_get(cal, UCAL_ZONE_OFFSET, &status);
1367     offset += ucal_get(cal, UCAL_DST_OFFSET, &status);
1368 
1369     if (U_FAILURE(status)) {
1370         log_err("ucal_get() failed: %s\n", u_errorName(status));
1371         goto cleanup;
1372     }
1373     temp=(double)((double)offset / 1000.0 / 60.0 / 60.0);
1374     /*printf("offset for %s %f hr\n", austrdup(myDateFormat(datfor, date1)), temp);*/
1375 
1376     utc = ((ucal_get(cal, UCAL_HOUR_OF_DAY, &status) * 60 +
1377                     ucal_get(cal, UCAL_MINUTE, &status)) * 60 +
1378                    ucal_get(cal, UCAL_SECOND, &status)) * 1000 +
1379                     ucal_get(cal, UCAL_MILLISECOND, &status) - offset;
1380     if (U_FAILURE(status)) {
1381         log_err("ucal_get() failed: %s\n", u_errorName(status));
1382         goto cleanup;
1383     }
1384 
1385     expected = ((hr * 60 + mn) * 60 + sc) * 1000;
1386     if (utc != expected) {
1387         temp=(double)(utc - expected)/ 1000 / 60 / 60.0;
1388         log_err("FAIL: Discrepancy of %d  millis = %fhr\n", utc-expected, temp );
1389     }
1390     else
1391         log_verbose("PASS: the offset between local and GMT is correct\n");
1392 
1393 cleanup:
1394     ucal_close(gmtcal);
1395     ucal_close(cal);
1396     udat_close(datfor);
1397 }
1398 
1399 /* ------------------------------------- */
1400 
1401 
1402 
1403 
1404 /* INTERNAL FUNCTIONS USED */
1405 /*------------------------------------------------------------------------------------------- */
1406 
1407 /* ------------------------------------- */
checkDateTime(UCalendar * c,int32_t y,int32_t m,int32_t d,int32_t hr,int32_t min,int32_t sec,int32_t ms,UCalendarDateFields field)1408 static void checkDateTime(UCalendar* c,
1409                         int32_t y, int32_t m, int32_t d,
1410                         int32_t hr, int32_t min, int32_t sec,
1411                         int32_t ms, UCalendarDateFields field)
1412 
1413 {
1414     UErrorCode status = U_ZERO_ERROR;
1415     if (ucal_get(c, UCAL_YEAR, &status) != y ||
1416         ucal_get(c, UCAL_MONTH, &status) != m ||
1417         ucal_get(c, UCAL_DATE, &status) != d ||
1418         ucal_get(c, UCAL_HOUR, &status) != hr ||
1419         ucal_get(c, UCAL_MINUTE, &status) != min ||
1420         ucal_get(c, UCAL_SECOND, &status) != sec ||
1421         ucal_get(c, UCAL_MILLISECOND, &status) != ms) {
1422         log_err("U_FAILURE for field  %d, Expected y/m/d h:m:s:ms of %d/%d/%d %d:%d:%d:%d  got %d/%d/%d %d:%d:%d:%d\n",
1423             (int32_t)field, y, m + 1, d, hr, min, sec, ms,
1424                     ucal_get(c, UCAL_YEAR, &status),
1425                     ucal_get(c, UCAL_MONTH, &status) + 1,
1426                     ucal_get(c, UCAL_DATE, &status),
1427                     ucal_get(c, UCAL_HOUR, &status),
1428                     ucal_get(c, UCAL_MINUTE, &status) + 1,
1429                     ucal_get(c, UCAL_SECOND, &status),
1430                     ucal_get(c, UCAL_MILLISECOND, &status) );
1431 
1432                     if (U_FAILURE(status)){
1433                     log_err("ucal_get failed: %s\n", u_errorName(status));
1434                     return;
1435                     }
1436 
1437      }
1438     else
1439         log_verbose("Confirmed: %d/%d/%d %d:%d:%d:%d\n", y, m + 1, d, hr, min, sec, ms);
1440 
1441 }
1442 
1443 /* ------------------------------------- */
checkDate(UCalendar * c,int32_t y,int32_t m,int32_t d)1444 static void checkDate(UCalendar* c, int32_t y, int32_t m, int32_t d)
1445 {
1446     UErrorCode status = U_ZERO_ERROR;
1447     if (ucal_get(c,UCAL_YEAR, &status) != y ||
1448         ucal_get(c, UCAL_MONTH, &status) != m ||
1449         ucal_get(c, UCAL_DATE, &status) != d) {
1450 
1451         log_err("FAILURE: Expected y/m/d of %d/%d/%d  got %d/%d/%d\n", y, m + 1, d,
1452                     ucal_get(c, UCAL_YEAR, &status),
1453                     ucal_get(c, UCAL_MONTH, &status) + 1,
1454                     ucal_get(c, UCAL_DATE, &status) );
1455 
1456         if (U_FAILURE(status)) {
1457             log_err("ucal_get failed: %s\n", u_errorName(status));
1458             return;
1459         }
1460     }
1461     else
1462         log_verbose("Confirmed: %d/%d/%d\n", y, m + 1, d);
1463 
1464 
1465 }
1466 
1467 /* ------------------------------------- */
1468 
1469 /* ------------------------------------- */
1470 
verify1(const char * msg,UCalendar * c,UDateFormat * dat,int32_t year,int32_t month,int32_t day)1471 static void verify1(const char* msg, UCalendar* c, UDateFormat* dat, int32_t year, int32_t month, int32_t day)
1472 {
1473     UDate d1;
1474     UErrorCode status = U_ZERO_ERROR;
1475     if (ucal_get(c, UCAL_YEAR, &status) == year &&
1476         ucal_get(c, UCAL_MONTH, &status) == month &&
1477         ucal_get(c, UCAL_DATE, &status) == day) {
1478         if (U_FAILURE(status)) {
1479             log_err("FAIL: Calendar::get failed: %s\n", u_errorName(status));
1480             return;
1481         }
1482         log_verbose("PASS: %s\n", msg);
1483         d1=ucal_getMillis(c, &status);
1484         if (U_FAILURE(status)) {
1485             log_err("ucal_getMillis failed: %s\n", u_errorName(status));
1486             return;
1487         }
1488     /*log_verbose(austrdup(myDateFormat(dat, d1)) );*/
1489     }
1490     else {
1491         log_err("FAIL: %s\n", msg);
1492         d1=ucal_getMillis(c, &status);
1493         if (U_FAILURE(status)) {
1494             log_err("ucal_getMillis failed: %s\n", u_errorName(status) );
1495             return;
1496         }
1497         log_err("Got %s  Expected %d/%d/%d \n", austrdup(myDateFormat(dat, d1)), year, month + 1, day );
1498         return;
1499     }
1500 
1501 
1502 }
1503 
1504 /* ------------------------------------ */
verify2(const char * msg,UCalendar * c,UDateFormat * dat,int32_t year,int32_t month,int32_t day,int32_t hour,int32_t min,int32_t sec,int32_t am_pm)1505 static void verify2(const char* msg, UCalendar* c, UDateFormat* dat, int32_t year, int32_t month, int32_t day,
1506                                                                      int32_t hour, int32_t min, int32_t sec, int32_t am_pm)
1507 {
1508     UDate d1;
1509     UErrorCode status = U_ZERO_ERROR;
1510     char tempMsgBuf[256];
1511 
1512     if (ucal_get(c, UCAL_YEAR, &status) == year &&
1513         ucal_get(c, UCAL_MONTH, &status) == month &&
1514         ucal_get(c, UCAL_DATE, &status) == day &&
1515         ucal_get(c, UCAL_HOUR, &status) == hour &&
1516         ucal_get(c, UCAL_MINUTE, &status) == min &&
1517         ucal_get(c, UCAL_SECOND, &status) == sec &&
1518         ucal_get(c, UCAL_AM_PM, &status) == am_pm ){
1519         if (U_FAILURE(status)) {
1520             log_err("FAIL: Calendar::get failed: %s\n", u_errorName(status));
1521             return;
1522         }
1523         log_verbose("PASS: %s\n", msg);
1524         d1=ucal_getMillis(c, &status);
1525         if (U_FAILURE(status)) {
1526             log_err("ucal_getMillis failed: %s\n", u_errorName(status));
1527             return;
1528         }
1529         log_verbose("%s\n" , u_austrcpy(tempMsgBuf, myDateFormat(dat, d1)) );
1530     }
1531     else {
1532         log_err("FAIL: %s\n", msg);
1533         d1=ucal_getMillis(c, &status);
1534         if (U_FAILURE(status)) {
1535             log_err("ucal_getMillis failed: %s\n", u_errorName(status));
1536             return;
1537         }
1538         log_err("Got %s Expected %d/%d/%d/ %d:%d:%d  %s\n", austrdup(myDateFormat(dat, d1)),
1539             year, month + 1, day, hour, min, sec, (am_pm==0) ? "AM": "PM");
1540 
1541         return;
1542     }
1543 
1544 
1545 }
1546 
TestGregorianChange()1547 void TestGregorianChange() {
1548     static const UChar utc[] = { 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0 }; /* "Etc/GMT" */
1549     const int32_t dayMillis = 86400 * INT64_C(1000);    /* 1 day = 86400 seconds */
1550     UCalendar *cal;
1551     UDate date;
1552     UErrorCode errorCode = U_ZERO_ERROR;
1553 
1554     /* Test ucal_setGregorianChange() on a Gregorian calendar. */
1555     errorCode = U_ZERO_ERROR;
1556     cal = ucal_open(utc, -1, "", UCAL_GREGORIAN, &errorCode);
1557     if(U_FAILURE(errorCode)) {
1558         log_data_err("ucal_open(UTC) failed: %s - (Are you missing data?)\n", u_errorName(errorCode));
1559         return;
1560     }
1561     ucal_setGregorianChange(cal, -365 * (dayMillis * (UDate)1), &errorCode);
1562     if(U_FAILURE(errorCode)) {
1563         log_err("ucal_setGregorianChange(1969) failed: %s\n", u_errorName(errorCode));
1564     } else {
1565         date = ucal_getGregorianChange(cal, &errorCode);
1566         if(U_FAILURE(errorCode) || date != -365 * (dayMillis * (UDate)1)) {
1567             log_err("ucal_getGregorianChange() failed: %s, date = %f\n", u_errorName(errorCode), date);
1568         }
1569     }
1570     ucal_close(cal);
1571 
1572     /* Test ucal_setGregorianChange() on a non-Gregorian calendar where it should fail. */
1573     errorCode = U_ZERO_ERROR;
1574     cal = ucal_open(utc, -1, "th@calendar=buddhist", UCAL_TRADITIONAL, &errorCode);
1575     if(U_FAILURE(errorCode)) {
1576         log_err("ucal_open(UTC, non-Gregorian) failed: %s\n", u_errorName(errorCode));
1577         return;
1578     }
1579     ucal_setGregorianChange(cal, -730 * (dayMillis * (UDate)1), &errorCode);
1580     if(errorCode != U_UNSUPPORTED_ERROR) {
1581         log_err("ucal_setGregorianChange(non-Gregorian calendar) did not yield U_UNSUPPORTED_ERROR but %s\n",
1582                 u_errorName(errorCode));
1583     }
1584     errorCode = U_ZERO_ERROR;
1585     date = ucal_getGregorianChange(cal, &errorCode);
1586     if(errorCode != U_UNSUPPORTED_ERROR) {
1587         log_err("ucal_getGregorianChange(non-Gregorian calendar) did not yield U_UNSUPPORTED_ERROR but %s\n",
1588                 u_errorName(errorCode));
1589     }
1590     ucal_close(cal);
1591 }
1592 
TestGetKeywordValuesForLocale()1593 static void TestGetKeywordValuesForLocale() {
1594 #define PREFERRED_SIZE 16
1595 #define MAX_NUMBER_OF_KEYWORDS 5
1596     const char *PREFERRED[PREFERRED_SIZE][MAX_NUMBER_OF_KEYWORDS+1] = {
1597             { "root",        "gregorian", NULL, NULL, NULL, NULL },
1598             { "und",         "gregorian", NULL, NULL, NULL, NULL },
1599             { "en_US",       "gregorian", NULL, NULL, NULL, NULL },
1600             { "en_029",      "gregorian", NULL, NULL, NULL, NULL },
1601             { "th_TH",       "buddhist", "gregorian", NULL, NULL, NULL },
1602             { "und_TH",      "buddhist", "gregorian", NULL, NULL, NULL },
1603             { "en_TH",       "buddhist", "gregorian", NULL, NULL, NULL },
1604             { "he_IL",       "gregorian", "hebrew", "islamic", "islamic-civil", "islamic-tbla" },
1605             { "ar_EG",       "gregorian", "coptic", "islamic", "islamic-civil", "islamic-tbla" },
1606             { "ja",          "gregorian", "japanese", NULL, NULL, NULL },
1607             { "ps_Guru_IN",  "gregorian", "indian", NULL, NULL, NULL },
1608             { "th@calendar=gregorian", "buddhist", "gregorian", NULL, NULL, NULL },
1609             { "en@calendar=islamic",   "gregorian", NULL, NULL, NULL, NULL },
1610             { "zh_TW",       "gregorian", "roc", "chinese", NULL, NULL },
1611             { "ar_IR",       "persian", "gregorian", "islamic", "islamic-civil", "islamic-tbla" },
1612             { "th@rg=SAZZZZ", "islamic-umalqura", "gregorian", "islamic", "islamic-rgsa", NULL },
1613     };
1614     const int32_t EXPECTED_SIZE[PREFERRED_SIZE] = { 1, 1, 1, 1, 2, 2, 2, 5, 5, 2, 2, 2, 1, 3, 5, 4 };
1615     UErrorCode status = U_ZERO_ERROR;
1616     int32_t i, size, j;
1617     UEnumeration *all, *pref;
1618     const char *loc = NULL;
1619     UBool matchPref, matchAll;
1620     const char *value;
1621     int32_t valueLength;
1622     UList *ALLList = NULL;
1623 
1624     UEnumeration *ALL = ucal_getKeywordValuesForLocale("calendar", uloc_getDefault(), false, &status);
1625     if (U_SUCCESS(status)) {
1626         for (i = 0; i < PREFERRED_SIZE; i++) {
1627             pref = NULL;
1628             all = NULL;
1629             loc = PREFERRED[i][0];
1630             pref = ucal_getKeywordValuesForLocale("calendar", loc, true, &status);
1631             matchPref = false;
1632             matchAll = false;
1633 
1634             value = NULL;
1635             valueLength = 0;
1636 
1637             if (U_SUCCESS(status) && uenum_count(pref, &status) == EXPECTED_SIZE[i]) {
1638                 matchPref = true;
1639                 for (j = 0; j < EXPECTED_SIZE[i]; j++) {
1640                     if ((value = uenum_next(pref, &valueLength, &status)) != NULL && U_SUCCESS(status)) {
1641                         if (uprv_strcmp(value, PREFERRED[i][j+1]) != 0) {
1642                             matchPref = false;
1643                             break;
1644                         }
1645                     } else {
1646                         matchPref = false;
1647                         log_err("ERROR getting keyword value for locale \"%s\"\n", loc);
1648                         break;
1649                     }
1650                 }
1651             }
1652 
1653             if (!matchPref) {
1654                 log_err("FAIL: Preferred values for locale \"%s\" does not match expected.\n", loc);
1655                 break;
1656             }
1657             uenum_close(pref);
1658 
1659             all = ucal_getKeywordValuesForLocale("calendar", loc, false, &status);
1660 
1661             size = uenum_count(all, &status);
1662 
1663             if (U_SUCCESS(status) && size == uenum_count(ALL, &status)) {
1664                 matchAll = true;
1665                 ALLList = ulist_getListFromEnum(ALL);
1666                 for (j = 0; j < size; j++) {
1667                     if ((value = uenum_next(all, &valueLength, &status)) != NULL && U_SUCCESS(status)) {
1668                         if (!ulist_containsString(ALLList, value, (int32_t)uprv_strlen(value))) {
1669                             log_err("Locale %s have %s not in ALL\n", loc, value);
1670                             matchAll = false;
1671                             break;
1672                         }
1673                     } else {
1674                         matchAll = false;
1675                         log_err("ERROR getting \"all\" keyword value for locale \"%s\"\n", loc);
1676                         break;
1677                     }
1678                 }
1679             }
1680             if (!matchAll) {
1681                 log_err("FAIL: All values for locale \"%s\" does not match expected.\n", loc);
1682             }
1683 
1684             uenum_close(all);
1685         }
1686     } else {
1687         log_err_status(status, "Failed to get ALL keyword values for default locale %s: %s.\n", uloc_getDefault(), u_errorName(status));
1688     }
1689     uenum_close(ALL);
1690 }
1691 
1692 /*
1693  * Weekend tests, ported from
1694  * icu4j/trunk/main/tests/core/src/com/ibm/icu/dev/test/calendar/IBMCalendarTest.java
1695  * and extended a bit. Notes below from IBMCalendarTest.java ...
1696  * This test tests for specific locale data. This is probably okay
1697  * as far as US data is concerned, but if the Arabic/Yemen data
1698  * changes, this test will have to be updated.
1699  */
1700 
1701 typedef struct {
1702     int32_t year;
1703     int32_t month;
1704     int32_t day;
1705     int32_t hour;
1706     int32_t millisecOffset;
1707     UBool   isWeekend;
1708 } TestWeekendDates;
1709 typedef struct {
1710     const char * locale;
1711     const        TestWeekendDates * dates;
1712     int32_t      numDates;
1713 } TestWeekendDatesList;
1714 
1715 static const TestWeekendDates weekendDates_en_US[] = {
1716     { 2000, UCAL_MARCH, 17, 23,  0, 0 }, /* Fri 23:00        */
1717     { 2000, UCAL_MARCH, 18,  0, -1, 0 }, /* Fri 23:59:59.999 */
1718     { 2000, UCAL_MARCH, 18,  0,  0, 1 }, /* Sat 00:00        */
1719     { 2000, UCAL_MARCH, 18, 15,  0, 1 }, /* Sat 15:00        */
1720     { 2000, UCAL_MARCH, 19, 23,  0, 1 }, /* Sun 23:00        */
1721     { 2000, UCAL_MARCH, 20,  0, -1, 1 }, /* Sun 23:59:59.999 */
1722     { 2000, UCAL_MARCH, 20,  0,  0, 0 }, /* Mon 00:00        */
1723     { 2000, UCAL_MARCH, 20,  8,  0, 0 }, /* Mon 08:00        */
1724 };
1725 static const TestWeekendDates weekendDates_ar_OM[] = {
1726     { 2000, UCAL_MARCH, 15, 23,  0, 0 }, /* Wed 23:00        */
1727     { 2000, UCAL_MARCH, 16,  0, -1, 0 }, /* Wed 23:59:59.999 */
1728     { 2000, UCAL_MARCH, 16,  0,  0, 0 }, /* Thu 00:00        */
1729     { 2000, UCAL_MARCH, 16, 15,  0, 0 }, /* Thu 15:00        */
1730     { 2000, UCAL_MARCH, 17, 23,  0, 1 }, /* Fri 23:00        */
1731     { 2000, UCAL_MARCH, 18,  0, -1, 1 }, /* Fri 23:59:59.999 */
1732     { 2000, UCAL_MARCH, 18,  0,  0, 1 }, /* Sat 00:00        */
1733     { 2000, UCAL_MARCH, 18,  8,  0, 1 }, /* Sat 08:00        */
1734 };
1735 static const TestWeekendDatesList testDates[] = {
1736     { "en_US", weekendDates_en_US, UPRV_LENGTHOF(weekendDates_en_US) },
1737     { "ar_OM", weekendDates_ar_OM, UPRV_LENGTHOF(weekendDates_ar_OM) },
1738 };
1739 
1740 typedef struct {
1741     UCalendarDaysOfWeek  dayOfWeek;
1742     UCalendarWeekdayType dayType;
1743     int32_t              transition; /* transition time if dayType is UCAL_WEEKEND_ONSET or UCAL_WEEKEND_CEASE; else must be 0 */
1744 } TestDaysOfWeek;
1745 typedef struct {
1746     const char *           locale;
1747     const TestDaysOfWeek * days;
1748     int32_t                numDays;
1749 } TestDaysOfWeekList;
1750 
1751 static const TestDaysOfWeek daysOfWeek_en_US[] = {
1752     { UCAL_MONDAY,   UCAL_WEEKDAY,       0        },
1753     { UCAL_FRIDAY,   UCAL_WEEKDAY,       0        },
1754     { UCAL_SATURDAY, UCAL_WEEKEND,       0        },
1755     { UCAL_SUNDAY,   UCAL_WEEKEND,       0        },
1756 };
1757 static const TestDaysOfWeek daysOfWeek_ar_OM[] = { /* Friday:Saturday */
1758     { UCAL_WEDNESDAY,UCAL_WEEKDAY,       0        },
1759     { UCAL_THURSDAY, UCAL_WEEKDAY,       0        },
1760     { UCAL_FRIDAY,   UCAL_WEEKEND,       0        },
1761     { UCAL_SATURDAY, UCAL_WEEKEND,       0        },
1762 };
1763 static const TestDaysOfWeek daysOfWeek_hi_IN[] = { /* Sunday only */
1764     { UCAL_MONDAY,   UCAL_WEEKDAY,       0        },
1765     { UCAL_FRIDAY,   UCAL_WEEKDAY,       0        },
1766     { UCAL_SATURDAY, UCAL_WEEKDAY,       0        },
1767     { UCAL_SUNDAY,   UCAL_WEEKEND,       0        },
1768 };
1769 static const TestDaysOfWeekList testDays[] = {
1770     { "en_US", daysOfWeek_en_US, UPRV_LENGTHOF(daysOfWeek_en_US) },
1771     { "ar_OM", daysOfWeek_ar_OM, UPRV_LENGTHOF(daysOfWeek_ar_OM) },
1772     { "hi_IN", daysOfWeek_hi_IN, UPRV_LENGTHOF(daysOfWeek_hi_IN) },
1773     { "en_US@rg=OMZZZZ", daysOfWeek_ar_OM, UPRV_LENGTHOF(daysOfWeek_ar_OM) },
1774     { "hi@rg=USZZZZ",    daysOfWeek_en_US, UPRV_LENGTHOF(daysOfWeek_en_US) },
1775 };
1776 
1777 static const UChar logDateFormat[] = { 0x0045,0x0045,0x0045,0x0020,0x004D,0x004D,0x004D,0x0020,0x0064,0x0064,0x0020,0x0079,
1778                                        0x0079,0x0079,0x0079,0x0020,0x0047,0x0020,0x0048,0x0048,0x003A,0x006D,0x006D,0x003A,
1779                                        0x0073,0x0073,0x002E,0x0053,0x0053,0x0053,0 }; /* "EEE MMM dd yyyy G HH:mm:ss.SSS" */
1780 enum { kFormattedDateMax = 2*UPRV_LENGTHOF(logDateFormat) };
1781 
TestWeekend()1782 static void TestWeekend() {
1783     const TestWeekendDatesList * testDatesPtr = testDates;
1784     const TestDaysOfWeekList *   testDaysPtr = testDays;
1785     int32_t count, subCount;
1786 
1787     UErrorCode fmtStatus = U_ZERO_ERROR;
1788     UDateFormat * fmt = udat_open(UDAT_NONE, UDAT_NONE, "en", NULL, 0, NULL, 0, &fmtStatus);
1789     if (U_SUCCESS(fmtStatus)) {
1790         udat_applyPattern(fmt, false, logDateFormat, -1);
1791     } else {
1792         log_data_err("Unable to create UDateFormat - %s\n", u_errorName(fmtStatus));
1793         return;
1794     }
1795     for (count = UPRV_LENGTHOF(testDates); count-- > 0; ++testDatesPtr) {
1796         UErrorCode status = U_ZERO_ERROR;
1797         UCalendar * cal = ucal_open(NULL, 0, testDatesPtr->locale, UCAL_GREGORIAN, &status);
1798         log_verbose("locale: %s\n", testDatesPtr->locale);
1799         if (U_SUCCESS(status)) {
1800             const TestWeekendDates * weekendDatesPtr = testDatesPtr->dates;
1801             for (subCount = testDatesPtr->numDates; subCount--; ++weekendDatesPtr) {
1802                 UDate dateToTest;
1803                 UBool isWeekend;
1804                 char  fmtDateBytes[kFormattedDateMax] = "<could not format test date>"; /* initialize for failure */
1805 
1806                 ucal_clear(cal);
1807                 ucal_setDateTime(cal, weekendDatesPtr->year, weekendDatesPtr->month, weekendDatesPtr->day,
1808                                  weekendDatesPtr->hour, 0, 0, &status);
1809                 dateToTest = ucal_getMillis(cal, &status) + weekendDatesPtr->millisecOffset;
1810                 isWeekend = ucal_isWeekend(cal, dateToTest, &status);
1811                 if (U_SUCCESS(fmtStatus)) {
1812                     UChar fmtDate[kFormattedDateMax];
1813                     (void)udat_format(fmt, dateToTest, fmtDate, kFormattedDateMax, NULL, &fmtStatus);
1814                     if (U_SUCCESS(fmtStatus)) {
1815                         u_austrncpy(fmtDateBytes, fmtDate, kFormattedDateMax);
1816                         fmtDateBytes[kFormattedDateMax-1] = 0;
1817                     } else {
1818                         fmtStatus = U_ZERO_ERROR;
1819                     }
1820                 }
1821                 if ( U_FAILURE(status) ) {
1822                     log_err("FAIL: locale %s date %s isWeekend() status %s\n", testDatesPtr->locale, fmtDateBytes, u_errorName(status) );
1823                     status = U_ZERO_ERROR;
1824                 } else if ( (isWeekend!=0) != (weekendDatesPtr->isWeekend!=0) ) {
1825                     log_err("FAIL: locale %s date %s isWeekend %d, expected the opposite\n", testDatesPtr->locale, fmtDateBytes, isWeekend );
1826                 } else {
1827                     log_verbose("OK:   locale %s date %s isWeekend %d\n", testDatesPtr->locale, fmtDateBytes, isWeekend );
1828                 }
1829             }
1830             ucal_close(cal);
1831         } else {
1832             log_data_err("FAIL: ucal_open for locale %s failed: %s - (Are you missing data?)\n", testDatesPtr->locale, u_errorName(status) );
1833         }
1834     }
1835     if (U_SUCCESS(fmtStatus)) {
1836         udat_close(fmt);
1837     }
1838 
1839     for (count = UPRV_LENGTHOF(testDays); count-- > 0; ++testDaysPtr) {
1840         UErrorCode status = U_ZERO_ERROR;
1841         UCalendar * cal = ucal_open(NULL, 0, testDaysPtr->locale, UCAL_GREGORIAN, &status);
1842         log_verbose("locale: %s\n", testDaysPtr->locale);
1843         if (U_SUCCESS(status)) {
1844             const TestDaysOfWeek * daysOfWeekPtr = testDaysPtr->days;
1845             for (subCount = testDaysPtr->numDays; subCount--; ++daysOfWeekPtr) {
1846                 int32_t transition = 0;
1847                 UCalendarWeekdayType dayType = ucal_getDayOfWeekType(cal, daysOfWeekPtr->dayOfWeek, &status);
1848                 if ( dayType == UCAL_WEEKEND_ONSET || dayType == UCAL_WEEKEND_CEASE ) {
1849                     transition = ucal_getWeekendTransition(cal, daysOfWeekPtr->dayOfWeek, &status);
1850                 }
1851                 if ( U_FAILURE(status) ) {
1852                     log_err("FAIL: locale %s DOW %d getDayOfWeekType() status %s\n", testDaysPtr->locale, daysOfWeekPtr->dayOfWeek, u_errorName(status) );
1853                     status = U_ZERO_ERROR;
1854                 } else if ( dayType != daysOfWeekPtr->dayType || transition != daysOfWeekPtr->transition ) {
1855                     log_err("FAIL: locale %s DOW %d type %d, expected %d\n", testDaysPtr->locale, daysOfWeekPtr->dayOfWeek, dayType, daysOfWeekPtr->dayType );
1856                 } else {
1857                     log_verbose("OK:   locale %s DOW %d type %d\n", testDaysPtr->locale, daysOfWeekPtr->dayOfWeek, dayType );
1858                 }
1859             }
1860             ucal_close(cal);
1861         } else {
1862             log_data_err("FAIL: ucal_open for locale %s failed: %s - (Are you missing data?)\n", testDaysPtr->locale, u_errorName(status) );
1863         }
1864     }
1865 }
1866 
1867 /**
1868  * TestFieldDifference
1869  */
1870 
1871 typedef struct {
1872     const UChar * timezone;
1873     const char *  locale;
1874     UDate         start;
1875     UDate         target;
1876     UBool         progressive; /* true to compute progressive difference for each field, false to reset calendar after each call */
1877     int32_t       yDiff;
1878     int32_t       MDiff;
1879     int32_t       dDiff;
1880     int32_t       HDiff;
1881     int32_t       mDiff;
1882     int32_t       sDiff; /* 0x7FFFFFFF indicates overflow error expected */
1883 } TFDItem;
1884 
1885 static const UChar tzUSPacific[] = { 0x55,0x53,0x2F,0x50,0x61,0x63,0x69,0x66,0x69,0x63,0 }; /* "US/Pacific" */
1886 static const UChar tzGMT[] = { 0x47,0x4D,0x54,0 }; /* "GMT" */
1887 
1888 static const TFDItem tfdItems[] = {
1889     /* timezone    locale          start              target           progress yDf  MDf    dDf     HDf       mDf         sDf */
1890     /* For these we compute the progressive difference for each field - not resetting the calendar after each call */
1891     { tzUSPacific, "en_US",        1267459800000.0,   1277772600000.0,  true,     0,   3,    27,      9,       40,          0 }, /* 2010-Mar-01 08:10 -> 2010-Jun-28 17:50 */
1892     { tzUSPacific, "en_US",        1267459800000.0,   1299089280000.0,  true,     1,   0,     1,      1,       58,          0 }, /* 2010-Mar-01 08:10 -> 2011-Mar-02 10:08 */
1893     /* For these we compute the total difference for each field - resetting the calendar after each call */
1894     { tzGMT,       "en_US",        0.0,               1073692800000.0,  false,   34, 408, 12427, 298248, 17894880, 1073692800 }, /* 1970-Jan-01 00:00 -> 2004-Jan-10 00:00 */
1895     { tzGMT,       "en_US",        0.0,               1073779200000.0,  false,   34, 408, 12428, 298272, 17896320, 1073779200 }, /* 1970-Jan-01 00:00 -> 2004-Jan-11 00:00 */
1896     { tzGMT,       "en_US",        0.0,               2147472000000.0,  false,   68, 816, 24855, 596520, 35791200, 2147472000 }, /* 1970-Jan-01 00:00 -> 2038-Jan-19 00:00 */
1897     { tzGMT,       "en_US",        0.0,               2147558400000.0,  false,   68, 816, 24856, 596544, 35792640, 0x7FFFFFFF }, /* 1970-Jan-01 00:00 -> 2038-Jan-20 00:00, seconds diff overflow */
1898     { tzGMT,       "en_US",        0.0,              -1073692800000.0,  false,  -34,-408,-12427,-298248,-17894880,-1073692800 }, /* 1970-Jan-01 00:00 -> 1935-Dec-24 00:00 */
1899     { tzGMT,       "en_US",        0.0,              -1073779200000.0,  false,  -34,-408,-12428,-298272,-17896320,-1073779200 }, /* 1970-Jan-01 00:00 -> 1935-Dec-23 00:00 */
1900     /* check fwd/backward on either side of era boundary and across era boundary */
1901     { tzGMT,       "en_US",       -61978089600000.0,-61820409600000.0,  false,    4,  59,  1825,  43800,  2628000,  157680000 }, /* CE   5-Dec-31 00:00 -> CE  10-Dec-30 00:00 */
1902     { tzGMT,       "en_US",       -61820409600000.0,-61978089600000.0,  false,   -4, -59, -1825, -43800, -2628000, -157680000 }, /* CE  10-Dec-30 00:00 -> CE   5-Dec-31 00:00 */
1903     { tzGMT,       "en_US",       -62451129600000.0,-62293449600000.0,  false,    4,  59,  1825,  43800,  2628000,  157680000 }, /* BCE 10-Jan-04 00:00 -> BCE  5-Jan-03 00:00 */
1904     { tzGMT,       "en_US",       -62293449600000.0,-62451129600000.0,  false,   -4, -59, -1825, -43800, -2628000, -157680000 }, /* BCE  5-Jan-03 00:00 -> BCE 10-Jan-04 00:00 */
1905     { tzGMT,       "en_US",       -62293449600000.0,-61978089600000.0,  false,    9, 119,  3650,  87600,  5256000,  315360000 }, /* BCE  5-Jan-03 00:00 -> CE   5-Dec-31 00:00 */
1906     { tzGMT,       "en_US",       -61978089600000.0,-62293449600000.0,  false,   -9,-119, -3650, -87600, -5256000, -315360000 }, /* CE   5-Dec-31 00:00 -> BCE  5-Jan-03 00:00 */
1907     { tzGMT, "en@calendar=roc",    -1672704000000.0, -1515024000000.0,  false,    4,  59,  1825,  43800,  2628000,  157680000 }, /* MG   5-Dec-30 00:00 -> MG  10-Dec-29 00:00 */
1908     { tzGMT, "en@calendar=roc",    -1515024000000.0, -1672704000000.0,  false,   -4, -59, -1825, -43800, -2628000, -157680000 }, /* MG  10-Dec-29 00:00 -> MG   5-Dec-30 00:00 */
1909     { tzGMT, "en@calendar=roc",    -2145744000000.0, -1988064000000.0,  false,    4,  59,  1825,  43800,  2628000,  157680000 }, /* BMG 10-Jan-03 00:00 -> BMG  5-Jan-02 00:00 */
1910     { tzGMT, "en@calendar=roc",    -1988064000000.0, -2145744000000.0,  false,   -4, -59, -1825, -43800, -2628000, -157680000 }, /* BMG  5-Jan-02 00:00 -> BMG 10-Jan-03 00:00 */
1911     { tzGMT, "en@calendar=roc",    -1988064000000.0, -1672704000000.0,  false,    9, 119,  3650,  87600,  5256000,  315360000 }, /* BMG  5-Jan-02 00:00 -> MG   5-Dec-30 00:00 */
1912     { tzGMT, "en@calendar=roc",    -1672704000000.0, -1988064000000.0,  false,   -9,-119, -3650, -87600, -5256000, -315360000 }, /* MG   5-Dec-30 00:00 -> BMG  5-Jan-02 00:00 */
1913     { tzGMT, "en@calendar=coptic",-53026531200000.0,-52868851200000.0,  false,    4,  64,  1825,  43800,  2628000,  157680000 }, /* Er1  5-Nas-05 00:00 -> Er1 10-Nas-04 00:00 */
1914     { tzGMT, "en@calendar=coptic",-52868851200000.0,-53026531200000.0,  false,   -4, -64, -1825, -43800, -2628000, -157680000 }, /* Er1 10-Nas-04 00:00 -> Er1  5-Nas-05 00:00 */
1915     { tzGMT, "en@calendar=coptic",-53499571200000.0,-53341891200000.0,  false,    4,  64,  1825,  43800,  2628000,  157680000 }, /* Er0 10-Tou-04 00:00 -> Er0  5-Tou-02 00:00 */
1916     { tzGMT, "en@calendar=coptic",-53341891200000.0,-53499571200000.0,  false,   -4, -64, -1825, -43800, -2628000, -157680000 }, /* Er0  5-Tou-02 00:00 -> Er0 10-Tou-04 00:00 */
1917     { tzGMT, "en@calendar=coptic",-53341891200000.0,-53026531200000.0,  false,    9, 129,  3650,  87600,  5256000,  315360000 }, /* Er0  5-Tou-02 00:00 -> Er1  5-Nas-05 00:00 */
1918     { tzGMT, "en@calendar=coptic",-53026531200000.0,-53341891200000.0,  false,   -9,-129, -3650, -87600, -5256000, -315360000 }, /* Er1  5-Nas-05 00:00 -> Er0  5-Tou-02 00:00 */
1919     { NULL,        NULL,           0.0,               0.0,              false,    0,   0,     0,      0,        0,          0 }  /* terminator */
1920 };
1921 
TestFieldDifference()1922 void TestFieldDifference() {
1923     const TFDItem * tfdItemPtr;
1924     for (tfdItemPtr = tfdItems; tfdItemPtr->timezone != NULL; tfdItemPtr++) {
1925         UErrorCode status = U_ZERO_ERROR;
1926         UCalendar* ucal = ucal_open(tfdItemPtr->timezone, -1, tfdItemPtr->locale, UCAL_DEFAULT, &status);
1927         if (U_FAILURE(status)) {
1928             log_err("FAIL: for locale \"%s\", ucal_open had status %s\n", tfdItemPtr->locale, u_errorName(status) );
1929         } else {
1930             int32_t yDf, MDf, dDf, HDf, mDf, sDf;
1931             if (tfdItemPtr->progressive) {
1932                 ucal_setMillis(ucal, tfdItemPtr->start, &status);
1933                 yDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_YEAR, &status);
1934                 MDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_MONTH, &status);
1935                 dDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_DATE, &status);
1936                 HDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_HOUR, &status);
1937                 mDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_MINUTE, &status);
1938                 sDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_SECOND, &status);
1939                 if (U_FAILURE(status)) {
1940                     log_err("FAIL: for locale \"%s\", start %.1f, target %.1f, ucal_setMillis or ucal_getFieldDifference had status %s\n",
1941                             tfdItemPtr->locale, tfdItemPtr->start, tfdItemPtr->target, u_errorName(status) );
1942                 } else if ( yDf !=  tfdItemPtr->yDiff ||
1943                             MDf !=  tfdItemPtr->MDiff ||
1944                             dDf !=  tfdItemPtr->dDiff ||
1945                             HDf !=  tfdItemPtr->HDiff ||
1946                             mDf !=  tfdItemPtr->mDiff ||
1947                             sDf !=  tfdItemPtr->sDiff ) {
1948                     log_data_err("FAIL: for locale \"%s\", start %.1f, target %.1f, expected y-M-d-H-m-s progressive diffs %d-%d-%d-%d-%d-%d, got %d-%d-%d-%d-%d-%d\n",
1949                             tfdItemPtr->locale, tfdItemPtr->start, tfdItemPtr->target,
1950                             tfdItemPtr->yDiff, tfdItemPtr->MDiff, tfdItemPtr->dDiff, tfdItemPtr->HDiff, tfdItemPtr->mDiff, tfdItemPtr->sDiff,
1951                             yDf, MDf, dDf, HDf, mDf, sDf);
1952                 }
1953             } else {
1954                 ucal_setMillis(ucal, tfdItemPtr->start, &status);
1955                 yDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_YEAR, &status);
1956                 ucal_setMillis(ucal, tfdItemPtr->start, &status);
1957                 MDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_MONTH, &status);
1958                 ucal_setMillis(ucal, tfdItemPtr->start, &status);
1959                 dDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_DATE, &status);
1960                 ucal_setMillis(ucal, tfdItemPtr->start, &status);
1961                 HDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_HOUR, &status);
1962                 ucal_setMillis(ucal, tfdItemPtr->start, &status);
1963                 mDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_MINUTE, &status);
1964                 if (U_FAILURE(status)) {
1965                     log_err("FAIL: for locale \"%s\", start %.1f, target %.1f, ucal_setMillis or ucal_getFieldDifference (y-M-d-H-m) had status %s\n",
1966                             tfdItemPtr->locale, tfdItemPtr->start, tfdItemPtr->target, u_errorName(status) );
1967                 } else if ( yDf !=  tfdItemPtr->yDiff ||
1968                             MDf !=  tfdItemPtr->MDiff ||
1969                             dDf !=  tfdItemPtr->dDiff ||
1970                             HDf !=  tfdItemPtr->HDiff ||
1971                             mDf !=  tfdItemPtr->mDiff ) {
1972                     log_data_err("FAIL: for locale \"%s\", start %.1f, target %.1f, expected y-M-d-H-m total diffs %d-%d-%d-%d-%d, got %d-%d-%d-%d-%d\n",
1973                             tfdItemPtr->locale, tfdItemPtr->start, tfdItemPtr->target,
1974                             tfdItemPtr->yDiff, tfdItemPtr->MDiff, tfdItemPtr->dDiff, tfdItemPtr->HDiff, tfdItemPtr->mDiff,
1975                             yDf, MDf, dDf, HDf, mDf);
1976                 }
1977                 ucal_setMillis(ucal, tfdItemPtr->start, &status);
1978                 sDf = ucal_getFieldDifference(ucal, tfdItemPtr->target, UCAL_SECOND, &status);
1979                 if (tfdItemPtr->sDiff != 0x7FFFFFFF) {
1980                     if (U_FAILURE(status)) {
1981                         log_err("FAIL: for locale \"%s\", start %.1f, target %.1f, ucal_setMillis or ucal_getFieldDifference (seconds) had status %s\n",
1982                                 tfdItemPtr->locale, tfdItemPtr->start, tfdItemPtr->target, u_errorName(status) );
1983                     } else if (sDf !=  tfdItemPtr->sDiff) {
1984                         log_data_err("FAIL: for locale \"%s\", start %.1f, target %.1f, expected seconds progressive diff %d, got %d\n",
1985                                 tfdItemPtr->locale, tfdItemPtr->start, tfdItemPtr->target, tfdItemPtr->sDiff, sDf);
1986                     }
1987                 } else if (!U_FAILURE(status)) {
1988                     log_err("FAIL: for locale \"%s\", start %.1f, target %.1f, for ucal_getFieldDifference (seconds) expected overflow error, got none\n",
1989                             tfdItemPtr->locale, tfdItemPtr->start, tfdItemPtr->target );
1990                 }
1991             }
1992             ucal_close(ucal);
1993         }
1994     }
1995 }
1996 
TestAmbiguousWallTime()1997 void TestAmbiguousWallTime() {
1998     UErrorCode status = U_ZERO_ERROR;
1999     UChar tzID[32];
2000     UCalendar* ucal;
2001     UDate t, expected;
2002 
2003     u_uastrcpy(tzID, "America/New_York");
2004     ucal = ucal_open(tzID, -1, "en_US", UCAL_DEFAULT, &status);
2005     if (U_FAILURE(status)) {
2006         log_err("FAIL: Failed to create a calendar");
2007         return;
2008     }
2009 
2010     if (ucal_getAttribute(ucal, UCAL_REPEATED_WALL_TIME) != UCAL_WALLTIME_LAST) {
2011         log_err("FAIL: Default UCAL_REPEATED_WALL_TIME value is not UCAL_WALLTIME_LAST");
2012     }
2013 
2014     if (ucal_getAttribute(ucal, UCAL_SKIPPED_WALL_TIME) != UCAL_WALLTIME_LAST) {
2015         log_err("FAIL: Default UCAL_SKIPPED_WALL_TIME value is not UCAL_WALLTIME_LAST");
2016     }
2017 
2018     /* UCAL_WALLTIME_FIRST on US fall transition */
2019     ucal_setAttribute(ucal, UCAL_REPEATED_WALL_TIME, UCAL_WALLTIME_FIRST);
2020     ucal_clear(ucal);
2021     ucal_setDateTime(ucal, 2011, 11-1, 6, 1, 30, 0, &status);
2022     t = ucal_getMillis(ucal, &status);
2023     expected = 1320557400000.0; /* 2011-11-06T05:30:00Z */
2024     if (U_FAILURE(status)) {
2025         log_err("FAIL: Calculating time 2011-11-06 01:30:00 with UCAL_WALLTIME_FIRST - %s\n", u_errorName(status));
2026         status = U_ZERO_ERROR;
2027     } else if (t != expected) {
2028         log_data_err("FAIL: 2011-11-06 01:30:00 with UCAL_WALLTIME_FIRST - got: %f, expected: %f\n", t, expected);
2029     }
2030 
2031     /* UCAL_WALLTIME_LAST on US fall transition */
2032     ucal_setAttribute(ucal, UCAL_REPEATED_WALL_TIME, UCAL_WALLTIME_LAST);
2033     ucal_clear(ucal);
2034     ucal_setDateTime(ucal, 2011, 11-1, 6, 1, 30, 0, &status);
2035     t = ucal_getMillis(ucal, &status);
2036     expected = 1320561000000.0; /* 2011-11-06T06:30:00Z */
2037     if (U_FAILURE(status)) {
2038         log_err("FAIL: Calculating time 2011-11-06 01:30:00 with UCAL_WALLTIME_LAST - %s\n", u_errorName(status));
2039         status = U_ZERO_ERROR;
2040     } else if (t != expected) {
2041         log_data_err("FAIL: 2011-11-06 01:30:00 with UCAL_WALLTIME_LAST - got: %f, expected: %f\n", t, expected);
2042     }
2043 
2044     /* UCAL_WALLTIME_FIRST on US spring transition */
2045     ucal_setAttribute(ucal, UCAL_SKIPPED_WALL_TIME, UCAL_WALLTIME_FIRST);
2046     ucal_clear(ucal);
2047     ucal_setDateTime(ucal, 2011, 3-1, 13, 2, 30, 0, &status);
2048     t = ucal_getMillis(ucal, &status);
2049     expected = 1299997800000.0; /* 2011-03-13T06:30:00Z */
2050     if (U_FAILURE(status)) {
2051         log_err("FAIL: Calculating time 2011-03-13 02:30:00 with UCAL_WALLTIME_FIRST - %s\n", u_errorName(status));
2052         status = U_ZERO_ERROR;
2053     } else if (t != expected) {
2054         log_data_err("FAIL: 2011-03-13 02:30:00 with UCAL_WALLTIME_FIRST - got: %f, expected: %f\n", t, expected);
2055     }
2056 
2057     /* UCAL_WALLTIME_LAST on US spring transition */
2058     ucal_setAttribute(ucal, UCAL_SKIPPED_WALL_TIME, UCAL_WALLTIME_LAST);
2059     ucal_clear(ucal);
2060     ucal_setDateTime(ucal, 2011, 3-1, 13, 2, 30, 0, &status);
2061     t = ucal_getMillis(ucal, &status);
2062     expected = 1300001400000.0; /* 2011-03-13T07:30:00Z */
2063     if (U_FAILURE(status)) {
2064         log_err("FAIL: Calculating time 2011-03-13 02:30:00 with UCAL_WALLTIME_LAST - %s\n", u_errorName(status));
2065         status = U_ZERO_ERROR;
2066     } else if (t != expected) {
2067         log_data_err("FAIL: 2011-03-13 02:30:00 with UCAL_WALLTIME_LAST - got: %f, expected: %f\n", t, expected);
2068     }
2069 
2070     /* UCAL_WALLTIME_NEXT_VALID on US spring transition */
2071     ucal_setAttribute(ucal, UCAL_SKIPPED_WALL_TIME, UCAL_WALLTIME_NEXT_VALID);
2072     ucal_clear(ucal);
2073     ucal_setDateTime(ucal, 2011, 3-1, 13, 2, 30, 0, &status);
2074     t = ucal_getMillis(ucal, &status);
2075     expected = 1299999600000.0; /* 2011-03-13T07:00:00Z */
2076     if (U_FAILURE(status)) {
2077         log_err("FAIL: Calculating time 2011-03-13 02:30:00 with UCAL_WALLTIME_NEXT_VALID - %s\n", u_errorName(status));
2078         status = U_ZERO_ERROR;
2079     } else if (t != expected) {
2080         log_data_err("FAIL: 2011-03-13 02:30:00 with UCAL_WALLTIME_NEXT_VALID - got: %f, expected: %f\n", t, expected);
2081     }
2082 
2083     /* non-lenient on US spring transition */
2084     ucal_setAttribute(ucal, UCAL_LENIENT, 0);
2085     ucal_clear(ucal);
2086     ucal_setDateTime(ucal, 2011, 3-1, 13, 2, 30, 0, &status);
2087     t = ucal_getMillis(ucal, &status);
2088     if (U_SUCCESS(status)) {
2089         /* must return error */
2090         log_data_err("FAIL: Non-lenient did not fail with 2011-03-13 02:30:00\n");
2091         status = U_ZERO_ERROR;
2092     }
2093 
2094     ucal_close(ucal);
2095 }
2096 
2097 /**
2098  * TestAddRollEra0AndEraBounds, for #9226
2099  */
2100 
2101  typedef struct {
2102      const char * locale;
2103      UBool era0YearsGoBackwards; /* until we have API to get this, per #9393 */
2104  } EraTestItem;
2105 
2106 static const EraTestItem eraTestItems[] = {
2107     /* calendars with non-modern era 0 that goes backwards, max era == 1 */
2108     { "en@calendar=gregorian", true },
2109     { "en@calendar=roc", true },
2110     { "en@calendar=coptic", true },
2111     /* calendars with non-modern era 0 that goes forwards, max era > 1 */
2112     { "en@calendar=japanese", false },
2113     { "en@calendar=chinese", false },
2114     /* calendars with non-modern era 0 that goes forwards, max era == 1 */
2115     { "en@calendar=ethiopic", false },
2116     /* calendars with only one era  = 0, forwards */
2117     { "en@calendar=buddhist", false },
2118     { "en@calendar=hebrew", false },
2119     { "en@calendar=islamic", false },
2120     { "en@calendar=indian", false },
2121     { "en@calendar=persian", false },
2122     { "en@calendar=ethiopic-amete-alem", false },
2123     { NULL, false }
2124 };
2125 
2126 static const UChar zoneGMT[] = { 0x47,0x4D,0x54,0 };
2127 
TestAddRollEra0AndEraBounds()2128 void TestAddRollEra0AndEraBounds() {
2129     const EraTestItem * eraTestItemPtr;
2130     for (eraTestItemPtr = eraTestItems; eraTestItemPtr->locale != NULL; eraTestItemPtr++) {
2131         UErrorCode status = U_ZERO_ERROR;
2132         UCalendar *ucalTest = ucal_open(zoneGMT, -1, eraTestItemPtr->locale, UCAL_DEFAULT, &status);
2133         if ( U_SUCCESS(status) ) {
2134             int32_t yrBefore, yrAfter, yrMax, eraAfter, eraMax, eraNow;
2135 
2136             status = U_ZERO_ERROR;
2137             ucal_clear(ucalTest);
2138             ucal_set(ucalTest, UCAL_YEAR, 2);
2139             ucal_set(ucalTest, UCAL_ERA, 0);
2140             yrBefore = ucal_get(ucalTest, UCAL_YEAR, &status);
2141             ucal_add(ucalTest, UCAL_YEAR, 1, &status);
2142             yrAfter = ucal_get(ucalTest, UCAL_YEAR, &status);
2143             if (U_FAILURE(status)) {
2144                 log_err("FAIL: set era 0 year 2 then add 1 year and get year for %s, error %s\n",
2145                         eraTestItemPtr->locale, u_errorName(status));
2146             } else if ( (eraTestItemPtr->era0YearsGoBackwards && yrAfter>yrBefore) ||
2147                         (!eraTestItemPtr->era0YearsGoBackwards && yrAfter<yrBefore) ) {
2148                 log_err("FAIL: era 0 add 1 year does not move forward in time for %s\n", eraTestItemPtr->locale);
2149             }
2150 
2151             status = U_ZERO_ERROR;
2152             ucal_clear(ucalTest);
2153             ucal_set(ucalTest, UCAL_YEAR, 2);
2154             ucal_set(ucalTest, UCAL_ERA, 0);
2155             yrBefore = ucal_get(ucalTest, UCAL_YEAR, &status);
2156             ucal_roll(ucalTest, UCAL_YEAR, 1, &status);
2157             yrAfter = ucal_get(ucalTest, UCAL_YEAR, &status);
2158             if (U_FAILURE(status)) {
2159                 log_err("FAIL: set era 0 year 2 then roll 1 year and get year for %s, error %s\n",
2160                         eraTestItemPtr->locale, u_errorName(status));
2161             } else if ( (eraTestItemPtr->era0YearsGoBackwards && yrAfter>yrBefore) ||
2162                         (!eraTestItemPtr->era0YearsGoBackwards && yrAfter<yrBefore) ) {
2163                 log_err("FAIL: era 0 roll 1 year does not move forward in time for %s\n", eraTestItemPtr->locale);
2164             }
2165 
2166             status = U_ZERO_ERROR;
2167             ucal_clear(ucalTest);
2168             ucal_set(ucalTest, UCAL_YEAR, 1);
2169             ucal_set(ucalTest, UCAL_ERA, 0);
2170             if (eraTestItemPtr->era0YearsGoBackwards) {
2171                 ucal_roll(ucalTest, UCAL_YEAR, 1, &status); /* roll forward in time to era 0 boundary */
2172                 yrAfter = ucal_get(ucalTest, UCAL_YEAR, &status);
2173                 eraAfter = ucal_get(ucalTest, UCAL_ERA, &status);
2174                 if (U_FAILURE(status)) {
2175                     log_err("FAIL: set era 0 year 1 then roll 1 year and get year,era for %s, error %s\n",
2176                             eraTestItemPtr->locale, u_errorName(status));
2177                 /* all calendars with era0YearsGoBackwards have "unbounded" era0 year values, so we should pin at yr 1 */
2178                 } else if (eraAfter != 0 || yrAfter != 1) {
2179                     log_err("FAIL: era 0 roll 1 year from year 1 does not stay within era or pin to year 1 for %s (get era %d year %d)\n",
2180                             eraTestItemPtr->locale, eraAfter, yrAfter);
2181                 }
2182             } else {
2183                 /* roll backward in time to where era 0 years go negative, except for the Chinese
2184                    calendar, which uses negative eras instead of having years outside the range 1-60 */
2185                 const char * calType = ucal_getType(ucalTest, &status);
2186                 ucal_roll(ucalTest, UCAL_YEAR, -2, &status);
2187                 yrAfter = ucal_get(ucalTest, UCAL_YEAR, &status);
2188                 eraAfter = ucal_get(ucalTest, UCAL_ERA, &status);
2189                 if (U_FAILURE(status)) {
2190                     log_err("FAIL: set era 0 year 1 then roll -2 years and get year,era for %s, error %s\n",
2191                             eraTestItemPtr->locale, u_errorName(status));
2192                 } else if ( uprv_strcmp(calType,"chinese")!=0 && (eraAfter != 0 || yrAfter != -1) ) {
2193                     log_err("FAIL: era 0 roll -2 years from year 1 does not stay within era or produce year -1 for %s (get era %d year %d)\n",
2194                             eraTestItemPtr->locale, eraAfter, yrAfter);
2195                 }
2196             }
2197 
2198             status = U_ZERO_ERROR;
2199             ucal_clear(ucalTest);
2200             {
2201                 int32_t eraMin = ucal_getLimit(ucalTest, UCAL_ERA, UCAL_MINIMUM, &status);
2202                 const char * calType = ucal_getType(ucalTest, &status);
2203                 if (eraMin != 0 && uprv_strcmp(calType, "chinese") != 0) {
2204                     log_err("FAIL: ucal_getLimit returns minimum era %d (should be 0) for calType %s, error %s\n", eraMin, calType, u_errorName(status));
2205                 }
2206             }
2207 
2208             status = U_ZERO_ERROR;
2209             ucal_clear(ucalTest);
2210             ucal_set(ucalTest, UCAL_YEAR, 1);
2211             ucal_set(ucalTest, UCAL_ERA, 0);
2212             eraMax = ucal_getLimit(ucalTest, UCAL_ERA, UCAL_MAXIMUM, &status);
2213             if ( U_SUCCESS(status) && eraMax > 0 ) {
2214                 /* try similar tests for era 1 (if calendar has it), in which years always go forward */
2215                 status = U_ZERO_ERROR;
2216                 ucal_clear(ucalTest);
2217                 ucal_set(ucalTest, UCAL_YEAR, 2);
2218                 ucal_set(ucalTest, UCAL_ERA, 1);
2219                 yrBefore = ucal_get(ucalTest, UCAL_YEAR, &status);
2220                 ucal_add(ucalTest, UCAL_YEAR, 1, &status);
2221                 yrAfter = ucal_get(ucalTest, UCAL_YEAR, &status);
2222                 if (U_FAILURE(status)) {
2223                     log_err("FAIL: set era 1 year 2 then add 1 year and get year for %s, error %s\n",
2224                             eraTestItemPtr->locale, u_errorName(status));
2225                 } else if ( yrAfter<yrBefore ) {
2226                     log_err("FAIL: era 1 add 1 year does not move forward in time for %s\n", eraTestItemPtr->locale);
2227                 }
2228 
2229                 status = U_ZERO_ERROR;
2230                 ucal_clear(ucalTest);
2231                 ucal_set(ucalTest, UCAL_YEAR, 2);
2232                 ucal_set(ucalTest, UCAL_ERA, 1);
2233                 yrBefore = ucal_get(ucalTest, UCAL_YEAR, &status);
2234                 ucal_roll(ucalTest, UCAL_YEAR, 1, &status);
2235                 yrAfter = ucal_get(ucalTest, UCAL_YEAR, &status);
2236                 if (U_FAILURE(status)) {
2237                     log_err("FAIL: set era 1 year 2 then roll 1 year and get year for %s, error %s\n",
2238                             eraTestItemPtr->locale, u_errorName(status));
2239                 } else if ( yrAfter<yrBefore ) {
2240                     log_err("FAIL: era 1 roll 1 year does not move forward in time for %s\n", eraTestItemPtr->locale);
2241                 }
2242 
2243                 status = U_ZERO_ERROR;
2244                 ucal_clear(ucalTest);
2245                 ucal_set(ucalTest, UCAL_YEAR, 1);
2246                 ucal_set(ucalTest, UCAL_ERA, 1);
2247                 yrMax = ucal_getLimit(ucalTest, UCAL_YEAR, UCAL_ACTUAL_MAXIMUM, &status); /* max year value for era 1 */
2248                 ucal_roll(ucalTest, UCAL_YEAR, -1, &status); /* roll down which should pin or wrap to end */
2249                 yrAfter = ucal_get(ucalTest, UCAL_YEAR, &status);
2250                 eraAfter = ucal_get(ucalTest, UCAL_ERA, &status);
2251                 if (U_FAILURE(status)) {
2252                     log_err("FAIL: set era 1 year 1 then roll -1 year and get year,era for %s, error %s\n",
2253                             eraTestItemPtr->locale, u_errorName(status));
2254                 /* if yrMax is reasonable we should wrap to that, else we should pin at yr 1 */
2255                 } else if (yrMax >= 32768) {
2256                     if (eraAfter != 1 || yrAfter != 1) {
2257                         log_err("FAIL: era 1 roll -1 year from year 1 does not stay within era or pin to year 1 for %s (get era %d year %d)\n",
2258                                 eraTestItemPtr->locale, eraAfter, yrAfter);
2259                     }
2260                 } else if (eraAfter != 1 || yrAfter != yrMax) {
2261                     log_err("FAIL: era 1 roll -1 year from year 1 does not stay within era or wrap to year %d for %s (get era %d year %d)\n",
2262                             yrMax, eraTestItemPtr->locale, eraAfter, yrAfter);
2263                 } else {
2264                     /* now roll up which should wrap to beginning */
2265                     ucal_roll(ucalTest, UCAL_YEAR, 1, &status); /* now roll up which should wrap to beginning */
2266                     yrAfter = ucal_get(ucalTest, UCAL_YEAR, &status);
2267                     eraAfter = ucal_get(ucalTest, UCAL_ERA, &status);
2268                     if (U_FAILURE(status)) {
2269                         log_err("FAIL: era 1 roll 1 year from end and get year,era for %s, error %s\n",
2270                                 eraTestItemPtr->locale, u_errorName(status));
2271                     } else if (eraAfter != 1 || yrAfter != 1) {
2272                         log_err("FAIL: era 1 roll 1 year from year %d does not stay within era or wrap to year 1 for %s (get era %d year %d)\n",
2273                                 yrMax, eraTestItemPtr->locale, eraAfter, yrAfter);
2274                     }
2275                 }
2276 
2277                 /* if current era  > 1, try the same roll tests for current era */
2278                 ucal_setMillis(ucalTest, ucal_getNow(), &status);
2279                 eraNow = ucal_get(ucalTest, UCAL_ERA, &status);
2280                 if ( U_SUCCESS(status) && eraNow > 1 ) {
2281                     status = U_ZERO_ERROR;
2282                     ucal_clear(ucalTest);
2283                     ucal_set(ucalTest, UCAL_YEAR, 1);
2284                     ucal_set(ucalTest, UCAL_ERA, eraNow);
2285                     yrMax = ucal_getLimit(ucalTest, UCAL_YEAR, UCAL_ACTUAL_MAXIMUM, &status); /* max year value for this era */
2286                     ucal_roll(ucalTest, UCAL_YEAR, -1, &status);
2287                     yrAfter = ucal_get(ucalTest, UCAL_YEAR, &status);
2288                     eraAfter = ucal_get(ucalTest, UCAL_ERA, &status);
2289                     if (U_FAILURE(status)) {
2290                         log_err("FAIL: set era %d year 1 then roll -1 year and get year,era for %s, error %s\n",
2291                                 eraNow, eraTestItemPtr->locale, u_errorName(status));
2292                     /* if yrMax is reasonable we should wrap to that, else we should pin at yr 1 */
2293                     } else if (yrMax >= 32768) {
2294                         if (eraAfter != eraNow || yrAfter != 1) {
2295                             log_err("FAIL: era %d roll -1 year from year 1 does not stay within era or pin to year 1 for %s (get era %d year %d)\n",
2296                                     eraNow, eraTestItemPtr->locale, eraAfter, yrAfter);
2297                         }
2298                     } else if (eraAfter != eraNow || yrAfter != yrMax) {
2299                         log_err("FAIL: era %d roll -1 year from year 1 does not stay within era or wrap to year %d for %s (get era %d year %d)\n",
2300                                 eraNow, yrMax, eraTestItemPtr->locale, eraAfter, yrAfter);
2301                     } else {
2302                         /* now roll up which should wrap to beginning */
2303                         ucal_roll(ucalTest, UCAL_YEAR, 1, &status); /* now roll up which should wrap to beginning */
2304                         yrAfter = ucal_get(ucalTest, UCAL_YEAR, &status);
2305                         eraAfter = ucal_get(ucalTest, UCAL_ERA, &status);
2306                         if (U_FAILURE(status)) {
2307                             log_err("FAIL: era %d roll 1 year from end and get year,era for %s, error %s\n",
2308                                     eraNow, eraTestItemPtr->locale, u_errorName(status));
2309                         } else if (eraAfter != eraNow || yrAfter != 1) {
2310                             log_err("FAIL: era %d roll 1 year from year %d does not stay within era or wrap to year 1 for %s (get era %d year %d)\n",
2311                                     eraNow, yrMax, eraTestItemPtr->locale, eraAfter, yrAfter);
2312                         }
2313                     }
2314                 }
2315             }
2316 
2317             ucal_close(ucalTest);
2318         } else {
2319             log_data_err("FAIL: ucal_open fails for zone GMT, locale %s, UCAL_DEFAULT\n", eraTestItemPtr->locale);
2320         }
2321     }
2322 }
2323 
2324 /**
2325  * TestGetTZTransition, for #9606
2326  */
2327 
2328 typedef struct {
2329     const char *descrip;    /* test description */
2330     const UChar * zoneName; /* pointer to zero-terminated zone name */
2331     int32_t year;           /* starting point for test is gregorian calendar noon on day specified by y,M,d here */
2332     int32_t month;
2333     int32_t day;
2334     UBool hasPrev;          /* does it have a previous transition from starting point? If so we test inclusive from that */
2335     UBool hasNext;          /* does it have a next transition from starting point? If so we test inclusive from that */
2336 } TZTransitionItem;
2337 
2338 /* have zoneGMT above */
2339 static const UChar zoneUSPacific[] = { 0x55,0x53,0x2F,0x50,0x61,0x63,0x69,0x66,0x69,0x63,0 }; /* "US/Pacific" */
2340 static const UChar zoneCairo[]     = { 0x41,0x66,0x72,0x69,0x63,0x61,0x2F,0x43,0x61,0x69,0x72,0x6F,0 }; /* "Africa/Cairo", DST cancelled since 2011 */
2341 static const UChar zoneIceland[]   = { 0x41,0x74,0x6C,0x61,0x6E,0x74,0x69,0x63,0x2F,0x52,0x65,0x79,0x6B,0x6A,0x61,0x76,0x69,0x6B,0 }; /* "Atlantic/Reykjavik", always on DST (since when?) */
2342 
2343 static const TZTransitionItem tzTransitionItems[] = {
2344     { "USPacific mid 2012", zoneUSPacific, 2012, UCAL_JULY, 1, true , true  },
2345     { "USPacific mid  100", zoneUSPacific,  100, UCAL_JULY, 1, false, true  }, /* no transitions before 100 CE... */
2346     { "Cairo     mid 2012", zoneCairo,     2012, UCAL_JULY, 1, true , true  }, /* DST cancelled since 2011 (Changed since 2014c) */
2347     { "Iceland   mid 2012", zoneIceland,   2012, UCAL_JULY, 1, true , false }, /* always on DST */
2348     { NULL,                 NULL,             0,         0, 0, false, false } /* terminator */
2349 };
2350 
TestGetTZTransition()2351 void TestGetTZTransition() {
2352     UErrorCode status = U_ZERO_ERROR;
2353     UCalendar * ucal = ucal_open(zoneGMT, -1, "en", UCAL_GREGORIAN, &status);
2354     if ( U_SUCCESS(status) ) {
2355         const TZTransitionItem * itemPtr;
2356         for (itemPtr = tzTransitionItems; itemPtr->descrip != NULL; itemPtr++) {
2357             UDate curMillis;
2358             ucal_setTimeZone(ucal, itemPtr->zoneName, -1, &status);
2359             ucal_setDateTime(ucal, itemPtr->year, itemPtr->month, itemPtr->day, 12, 0, 0, &status);
2360             curMillis = ucal_getMillis(ucal, &status);
2361             (void)curMillis;    /* Suppress set but not used warning. */
2362             if ( U_SUCCESS(status) ) {
2363                 UDate transition1, transition2;
2364                 UBool result;
2365 
2366                 result = ucal_getTimeZoneTransitionDate(ucal, UCAL_TZ_TRANSITION_PREVIOUS, &transition1, &status);
2367                 if (U_FAILURE(status) || result != itemPtr->hasPrev) {
2368                     log_data_err("FAIL: %s ucal_getTimeZoneTransitionDate prev status %s, expected result %d but got %d\n",
2369                             itemPtr->descrip, u_errorName(status), itemPtr->hasPrev, result);
2370                 } else if (result) {
2371                     ucal_setMillis(ucal, transition1, &status);
2372                     result = ucal_getTimeZoneTransitionDate(ucal, UCAL_TZ_TRANSITION_PREVIOUS_INCLUSIVE, &transition2, &status);
2373                     if (U_FAILURE(status) || !result || transition2 != transition1) {
2374                         log_err("FAIL: %s ucal_getTimeZoneTransitionDate prev_inc status %s, result %d, expected date %.1f but got %.1f\n",
2375                                 itemPtr->descrip, u_errorName(status), result, transition1, transition2);
2376                     }
2377                 }
2378                 status = U_ZERO_ERROR;
2379 
2380                 result = ucal_getTimeZoneTransitionDate(ucal, UCAL_TZ_TRANSITION_NEXT, &transition1, &status);
2381                 if (U_FAILURE(status) || result != itemPtr->hasNext) {
2382                     log_data_err("FAIL: %s ucal_getTimeZoneTransitionDate next status %s, expected result %d but got %d\n",
2383                             itemPtr->descrip, u_errorName(status), itemPtr->hasNext, result);
2384                 } else if (result) {
2385                     ucal_setMillis(ucal, transition1, &status);
2386                     result = ucal_getTimeZoneTransitionDate(ucal, UCAL_TZ_TRANSITION_NEXT_INCLUSIVE, &transition2, &status);
2387                     if (U_FAILURE(status) || !result || transition2 != transition1) {
2388                         log_err("FAIL: %s ucal_getTimeZoneTransitionDate next_inc status %s, result %d, expected date %.1f but got %.1f\n",
2389                                 itemPtr->descrip, u_errorName(status), result, transition1, transition2);
2390                     }
2391                 }
2392                 status = U_ZERO_ERROR;
2393             } else {
2394                 log_data_err("FAIL setup: can't setup calendar for %s, status %s\n",
2395                             itemPtr->descrip, u_errorName(status));
2396                 status = U_ZERO_ERROR;
2397             }
2398         }
2399         ucal_close(ucal);
2400     } else {
2401         log_data_err("FAIL setup: ucal_open status %s\n", u_errorName(status));
2402     }
2403 }
2404 
2405 static const UChar winEastern[] = /* Eastern Standard Time */
2406     {0x45,0x61,0x73,0x74,0x65,0x72,0x6E,0x20,0x53,0x74,0x61,0x6E,0x64,0x61,0x72,0x64,0x20,0x54,0x69,0x6D,0x65,0x00};
2407 
2408 static const UChar tzNewYork[] = /* America/New_York */
2409     {0x41,0x6D,0x65,0x72,0x69,0x63,0x61,0x2F,0x4E,0x65,0x77,0x5F,0x59,0x6F,0x72,0x6B,0x00};
2410 static const UChar tzTronto[] = /* America/Toronto */
2411     {0x41,0x6D,0x65,0x72,0x69,0x63,0x61,0x2F,0x54,0x6F,0x72,0x6F,0x6E,0x74,0x6F,0x00};
2412 
2413 static const UChar sBogus[] = /* Bogus */
2414     {0x42,0x6F,0x67,0x75,0x73,0x00};
2415 
2416 #ifndef U_DEBUG
2417 static const UChar sBogusWithVariantCharacters[] = /* Bogus with Variant characters: Hèℓℓô Wôřℓδ */
2418     {0x48,0xE8,0x2113,0x2113,0xF4,0x20,0x57,0xF4,0x159,0x2113,0x3B4,0x00};
2419 #endif
2420 
TestGetWindowsTimeZoneID()2421 void TestGetWindowsTimeZoneID() {
2422     UErrorCode status;
2423     UChar winID[64];
2424     int32_t len;
2425 
2426     {
2427         status = U_ZERO_ERROR;
2428         len = ucal_getWindowsTimeZoneID(tzNewYork, u_strlen(tzNewYork), winID, UPRV_LENGTHOF(winID), &status);
2429         if (U_FAILURE(status)) {
2430             log_data_err("FAIL: Windows ID for America/New_York, status %s\n", u_errorName(status));
2431         } else if (len != u_strlen(winEastern) || u_strncmp(winID, winEastern, len) != 0) {
2432             log_data_err("FAIL: Windows ID for America/New_York\n");
2433         }
2434     }
2435     {
2436         status = U_ZERO_ERROR;
2437         len = ucal_getWindowsTimeZoneID(tzTronto, u_strlen(tzTronto), winID, UPRV_LENGTHOF(winID), &status);
2438         if (U_FAILURE(status)) {
2439             log_data_err("FAIL: Windows ID for America/Toronto, status %s\n", u_errorName(status));
2440         } else if (len != u_strlen(winEastern) || u_strncmp(winID, winEastern, len) != 0) {
2441             log_data_err("FAIL: Windows ID for America/Toronto\n");
2442         }
2443     }
2444     {
2445         status = U_ZERO_ERROR;
2446         len = ucal_getWindowsTimeZoneID(sBogus, u_strlen(sBogus), winID, UPRV_LENGTHOF(winID), &status);
2447         if (U_FAILURE(status)) {
2448             log_data_err("FAIL: Windows ID for Bogus, status %s\n", u_errorName(status));
2449         } else if (len != 0) {
2450             log_data_err("FAIL: Windows ID for Bogus\n");
2451         }
2452     }
2453 }
2454 
TestGetTimeZoneIDByWindowsID()2455 void TestGetTimeZoneIDByWindowsID() {
2456     UErrorCode status;
2457     UChar tzID[64];
2458     int32_t len;
2459 
2460     {
2461         status = U_ZERO_ERROR;
2462         len = ucal_getTimeZoneIDForWindowsID(winEastern, -1, NULL, tzID, UPRV_LENGTHOF(tzID), &status);
2463         if (U_FAILURE(status)) {
2464             log_data_err("FAIL: TZ ID for Eastern Standard Time, status %s\n", u_errorName(status));
2465         } else if (len != u_strlen(tzNewYork) || u_strncmp(tzID, tzNewYork, len) != 0) {
2466             log_err("FAIL: TZ ID for Eastern Standard Time\n");
2467         }
2468     }
2469     {
2470         status = U_ZERO_ERROR;
2471         len = ucal_getTimeZoneIDForWindowsID(winEastern, u_strlen(winEastern), "US", tzID, UPRV_LENGTHOF(tzID), &status);
2472         if (U_FAILURE(status)) {
2473             log_data_err("FAIL: TZ ID for Eastern Standard Time - US, status %s\n", u_errorName(status));
2474         } else if (len != u_strlen(tzNewYork) || u_strncmp(tzID, tzNewYork, len) != 0) {
2475             log_err("FAIL: TZ ID for Eastern Standard Time - US\n");
2476         }
2477     }
2478     {
2479         status = U_ZERO_ERROR;
2480         len = ucal_getTimeZoneIDForWindowsID(winEastern, u_strlen(winEastern), "CA", tzID, UPRV_LENGTHOF(tzID), &status);
2481         if (U_FAILURE(status)) {
2482             log_data_err("FAIL: TZ ID for Eastern Standard Time - CA, status %s\n", u_errorName(status));
2483         } else if (len != u_strlen(tzTronto) || u_strncmp(tzID, tzTronto, len) != 0) {
2484             log_err("FAIL: TZ ID for Eastern Standard Time - CA\n");
2485         }
2486     }
2487     {
2488         status = U_ZERO_ERROR;
2489         len = ucal_getTimeZoneIDForWindowsID(sBogus, -1, NULL, tzID, UPRV_LENGTHOF(tzID), &status);
2490         if (U_FAILURE(status)) {
2491             log_data_err("FAIL: TZ ID for Bogus, status %s\n", u_errorName(status));
2492         } else if (len != 0) {
2493             log_err("FAIL: TZ ID for Bogus\n");
2494         }
2495     }
2496 #ifndef U_DEBUG
2497     // This test is only for release mode because it will cause an assertion failure in debug builds.
2498     // We don't check the API result for errors as the only purpose of this test is to ensure that
2499     // input variant characters don't cause abort() to be called and/or that ICU doesn't crash.
2500     {
2501         status = U_ZERO_ERROR;
2502         len = ucal_getTimeZoneIDForWindowsID(sBogusWithVariantCharacters, -1, NULL, tzID, UPRV_LENGTHOF(tzID), &status);
2503     }
2504 #endif
2505 }
2506 
2507 // The following currently assumes that Reiwa is the last known/valid era.
2508 // Filed ICU-20551 to generalize this when we have more time...
TestJpnCalAddSetNextEra()2509 void TestJpnCalAddSetNextEra() {
2510     UErrorCode status = U_ZERO_ERROR;
2511     UCalendar *jCal = ucal_open(NULL, 0, "ja_JP@calendar=japanese", UCAL_DEFAULT, &status);
2512     if ( U_FAILURE(status) ) {
2513         log_data_err("FAIL: ucal_open for ja_JP@calendar=japanese, status %s\n", u_errorName(status));
2514     } else {
2515         ucal_clear(jCal); // This sets to 1970, in Showa
2516         int32_t sEra = ucal_get(jCal, UCAL_ERA, &status); // Don't assume era number for Showa
2517         if ( U_FAILURE(status) ) {
2518             log_data_err("FAIL: ucal_get ERA for Showa, status %s\n", u_errorName(status));
2519         } else {
2520             int32_t iEra, eYear;
2521             int32_t startYears[4] = { 1926, 1989, 2019, 0 }; // start years for Showa, Heisei, Reiwa; 0 marks invalid era
2522             for (iEra = 1; iEra < 3; iEra++) {
2523                 status = U_ZERO_ERROR;
2524                 ucal_clear(jCal);
2525                 ucal_set(jCal, UCAL_ERA, sEra+iEra);
2526                 eYear = ucal_get(jCal, UCAL_EXTENDED_YEAR, &status);
2527                 if ( U_FAILURE(status) ) {
2528                     log_err("FAIL: set %d, ucal_get EXTENDED_YEAR, status %s\n", iEra, u_errorName(status));
2529                 } else if (eYear != startYears[iEra]) {
2530                     log_err("ERROR: set %d, expected start year %d but get %d\n", iEra, startYears[iEra], eYear);
2531                 } else {
2532                     ucal_add(jCal, UCAL_ERA, 1, &status);
2533                     if ( U_FAILURE(status) ) {
2534                         log_err("FAIL: set %d, ucal_add ERA 1, status %s\n", iEra, u_errorName(status));
2535                     } else {
2536                         eYear = ucal_get(jCal, UCAL_EXTENDED_YEAR, &status);
2537                         if ( U_FAILURE(status) ) {
2538                             log_err("FAIL: set %d then add ERA 1, ucal_get EXTENDED_YEAR, status %s\n", iEra, u_errorName(status));
2539                         } else {
2540                             // If this is the last valid era, we expect adding an era to pin to the current era
2541                             int32_t nextEraStart = (startYears[iEra+1] == 0)? startYears[iEra]: startYears[iEra+1];
2542                             if (eYear != nextEraStart) {
2543                                 log_err("ERROR: set %d then add ERA 1, expected start year %d but get %d\n", iEra, nextEraStart, eYear);
2544                             }
2545                         }
2546                     }
2547                 }
2548              }
2549         }
2550         ucal_close(jCal);
2551     }
2552 }
2553 
TestUcalOpenBufferRead()2554 void TestUcalOpenBufferRead() {
2555     // ICU-21004: The issue shows under valgrind or as an Address Sanitizer failure.
2556     UErrorCode status = U_ZERO_ERROR;
2557     // string length: 157 + 1 + 100 = 258
2558     const char *localeID = "x-privatebutreallylongtagfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar-foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoorbarfoobarfoo";
2559     UCalendar *cal = ucal_open(NULL, 0, localeID, UCAL_GREGORIAN, &status);
2560     ucal_close(cal);
2561 }
2562 
2563 
2564 /*
2565  * Testing ucal_getTimeZoneOffsetFromLocal
2566  */
2567 void
TestGetTimeZoneOffsetFromLocal()2568 TestGetTimeZoneOffsetFromLocal() {
2569     static const UChar utc[] = u"Etc/GMT";
2570 
2571     const int32_t HOUR = 60*60*1000;
2572     const int32_t MINUTE = 60*1000;
2573 
2574     const int32_t DATES[][6] = {
2575         {2006, UCAL_APRIL, 2, 1, 30, 1*HOUR+30*MINUTE},
2576         {2006, UCAL_APRIL, 2, 2, 00, 2*HOUR},
2577         {2006, UCAL_APRIL, 2, 2, 30, 2*HOUR+30*MINUTE},
2578         {2006, UCAL_APRIL, 2, 3, 00, 3*HOUR},
2579         {2006, UCAL_APRIL, 2, 3, 30, 3*HOUR+30*MINUTE},
2580         {2006, UCAL_OCTOBER, 29, 0, 30, 0*HOUR+30*MINUTE},
2581         {2006, UCAL_OCTOBER, 29, 1, 00, 1*HOUR},
2582         {2006, UCAL_OCTOBER, 29, 1, 30, 1*HOUR+30*MINUTE},
2583         {2006, UCAL_OCTOBER, 29, 2, 00, 2*HOUR},
2584         {2006, UCAL_OCTOBER, 29, 2, 30, 2*HOUR+30*MINUTE},
2585     };
2586 
2587     // Expected offsets by
2588     // void U_ucal_getTimeZoneOffsetFromLocal(
2589     //   const UCalendar* cal,
2590     //   UTimeZoneLocalOption nonExistingTimeOpt,
2591     //   UTimeZoneLocalOption duplicatedTimeOpt,
2592     //   int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status);
2593     // with nonExistingTimeOpt=UCAL_TZ_LOCAL_STANDARD and
2594     // duplicatedTimeOpt=UCAL_TZ_LOCAL_STANDARD
2595     const int32_t OFFSETS2[][2] = {
2596         // April 2, 2006
2597         {-8*HOUR, 0},
2598         {-8*HOUR, 0},
2599         {-8*HOUR, 0},
2600         {-8*HOUR, 1*HOUR},
2601         {-8*HOUR, 1*HOUR},
2602 
2603         // Oct 29, 2006
2604         {-8*HOUR, 1*HOUR},
2605         {-8*HOUR, 0},
2606         {-8*HOUR, 0},
2607         {-8*HOUR, 0},
2608         {-8*HOUR, 0},
2609     };
2610 
2611     // Expected offsets by
2612     // void U_ucal_getTimeZoneOffsetFromLocal(
2613     //   const UCalendar* cal,
2614     //   UTimeZoneLocalOption nonExistingTimeOpt,
2615     //   UTimeZoneLocalOption duplicatedTimeOpt,
2616     //   int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status);
2617     // with nonExistingTimeOpt=UCAL_TZ_LOCAL_DAYLIGHT and
2618     // duplicatedTimeOpt=UCAL_TZ_LOCAL_DAYLIGHT
2619     const int32_t OFFSETS3[][2] = {
2620         // April 2, 2006
2621         {-8*HOUR, 0},
2622         {-8*HOUR, 1*HOUR},
2623         {-8*HOUR, 1*HOUR},
2624         {-8*HOUR, 1*HOUR},
2625         {-8*HOUR, 1*HOUR},
2626 
2627         // October 29, 2006
2628         {-8*HOUR, 1*HOUR},
2629         {-8*HOUR, 1*HOUR},
2630         {-8*HOUR, 1*HOUR},
2631         {-8*HOUR, 0},
2632         {-8*HOUR, 0},
2633     };
2634 
2635     UErrorCode status = U_ZERO_ERROR;
2636 
2637     int32_t rawOffset, dstOffset;
2638     UCalendar *cal = ucal_open(utc, -1, "en", UCAL_GREGORIAN, &status);
2639     if (U_FAILURE(status)) {
2640         log_data_err("ucal_open: %s", u_errorName(status));
2641         return;
2642     }
2643 
2644     // Calculate millis
2645     UDate MILLIS[UPRV_LENGTHOF(DATES)];
2646     for (int32_t i = 0; i < UPRV_LENGTHOF(DATES); i++) {
2647         ucal_setDateTime(cal, DATES[i][0], DATES[i][1], DATES[i][2],
2648                          DATES[i][3], DATES[i][4], 0, &status);
2649         MILLIS[i] = ucal_getMillis(cal, &status);
2650         if (U_FAILURE(status)) {
2651             log_data_err("ucal_getMillis failed");
2652             return;
2653         }
2654     }
2655     ucal_setTimeZone(cal, AMERICA_LOS_ANGELES, -1, &status);
2656 
2657     // Test void ucal_getTimeZoneOffsetFromLocal(
2658     // const UCalendar* cal,
2659     // UTimeZoneLocalOption nonExistingTimeOpt,
2660     // UTimeZoneLocalOption duplicatedTimeOpt,
2661     // int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status);
2662     // with nonExistingTimeOpt=UCAL_TZ_LOCAL_STANDARD and
2663     // duplicatedTimeOpt=UCAL_TZ_LOCAL_STANDARD
2664     for (int m = 0; m < UPRV_LENGTHOF(DATES); m++) {
2665         status = U_ZERO_ERROR;
2666         ucal_setMillis(cal, MILLIS[m], &status);
2667         if (U_FAILURE(status)) {
2668             log_data_err("ucal_setMillis: %s\n", u_errorName(status));
2669         }
2670 
2671         ucal_getTimeZoneOffsetFromLocal(cal, UCAL_TZ_LOCAL_STANDARD_FORMER, UCAL_TZ_LOCAL_STANDARD_LATTER,
2672             &rawOffset, &dstOffset, &status);
2673         if (U_FAILURE(status)) {
2674             log_err("ERROR: ucal_getTimeZoneOffsetFromLocal((%d-%d-%d %d:%d:0),"
2675                     "UCAL_TZ_LOCAL_STANDARD_FORMER, UCAL_TZ_LOCAL_STANDARD_LATTER: %s\n",
2676                     DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4],
2677                     u_errorName(status));
2678         } else if (rawOffset != OFFSETS2[m][0] || dstOffset != OFFSETS2[m][1]) {
2679             log_err("Bad offset returned at (%d-%d-%d %d:%d:0) "
2680                     "(wall/UCAL_TZ_LOCAL_STANDARD_FORMER/UCAL_TZ_LOCAL_STANDARD_LATTER) \n- Got: %d / %d "
2681                     " Expected %d / %d\n",
2682                     DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4],
2683                     rawOffset, dstOffset, OFFSETS2[m][0], OFFSETS2[m][1]);
2684         }
2685     }
2686 
2687     // Test void ucal_getTimeZoneOffsetFromLocal(
2688     // const UCalendar* cal,
2689     // UTimeZoneLocalOption nonExistingTimeOpt,
2690     // UTimeZoneLocalOption duplicatedTimeOpt,
2691     // int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status);
2692     // with nonExistingTimeOpt=UCAL_TZ_LOCAL_DAYLIGHT and
2693     // duplicatedTimeOpt=UCAL_TZ_LOCAL_DAYLIGHT
2694     for (int m = 0; m < UPRV_LENGTHOF(DATES); m++) {
2695         status = U_ZERO_ERROR;
2696         ucal_setMillis(cal, MILLIS[m], &status);
2697         if (U_FAILURE(status)) {
2698             log_data_err("ucal_setMillis: %s\n", u_errorName(status));
2699         }
2700 
2701         ucal_getTimeZoneOffsetFromLocal(cal, UCAL_TZ_LOCAL_DAYLIGHT_LATTER, UCAL_TZ_LOCAL_DAYLIGHT_FORMER,
2702             &rawOffset, &dstOffset, &status);
2703         if (U_FAILURE(status)) {
2704             log_err("ERROR: ucal_getTimeZoneOffsetFromLocal((%d-%d-%d %d:%d:0),"
2705                     "UCAL_TZ_LOCAL_DAYLIGHT_LATTER, UCAL_TZ_LOCAL_DAYLIGHT_FORMER: %s\n",
2706                     DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4],
2707                     u_errorName(status));
2708         } else if (rawOffset != OFFSETS3[m][0] || dstOffset != OFFSETS3[m][1]) {
2709             log_err("Bad offset returned at (%d-%d-%d %d:%d:0) "
2710                     "(wall/UCAL_TZ_LOCAL_DAYLIGHT_LATTER/UCAL_TZ_LOCAL_DAYLIGHT_FORMER) \n- Got: %d / %d "
2711                     " Expected %d / %d\n",
2712                     DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4],
2713                     rawOffset, dstOffset, OFFSETS3[m][0], OFFSETS3[m][1]);
2714         }
2715     }
2716 
2717     // Test void ucal_getTimeZoneOffsetFromLocal(
2718     // const UCalendar* cal,
2719     // UTimeZoneLocalOption nonExistingTimeOpt,
2720     // UTimeZoneLocalOption duplicatedTimeOpt,
2721     // int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status);
2722     // with nonExistingTimeOpt=UCAL_TZ_LOCAL_FORMER and
2723     // duplicatedTimeOpt=UCAL_TZ_LOCAL_LATTER
2724     for (int m = 0; m < UPRV_LENGTHOF(DATES); m++) {
2725         status = U_ZERO_ERROR;
2726         ucal_setMillis(cal, MILLIS[m], &status);
2727         if (U_FAILURE(status)) {
2728             log_data_err("ucal_setMillis: %s\n", u_errorName(status));
2729         }
2730 
2731         ucal_getTimeZoneOffsetFromLocal(cal, UCAL_TZ_LOCAL_FORMER, UCAL_TZ_LOCAL_LATTER,
2732             &rawOffset, &dstOffset, &status);
2733         if (U_FAILURE(status)) {
2734             log_err("ERROR: ucal_getTimeZoneOffsetFromLocal((%d-%d-%d %d:%d:0),"
2735                     "UCAL_TZ_LOCAL_FORMER, UCAL_TZ_LOCAL_LATTER: %s\n",
2736                     DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4],
2737                     u_errorName(status));
2738         } else if (rawOffset != OFFSETS2[m][0] || dstOffset != OFFSETS2[m][1]) {
2739             log_err("Bad offset returned at (%d-%d-%d %d:%d:0) "
2740                     "(wall/UCAL_TZ_LOCAL_FORMER/UCAL_TZ_LOCAL_LATTER) \n- Got: %d / %d "
2741                     " Expected %d / %d\n",
2742                     DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4],
2743                     rawOffset, dstOffset, OFFSETS2[m][0], OFFSETS2[m][1]);
2744         }
2745     }
2746 
2747     // Test void ucal_getTimeZoneOffsetFromLocal(
2748     // const UCalendar* cal,
2749     // UTimeZoneLocalOption nonExistingTimeOpt,
2750     // UTimeZoneLocalOption duplicatedTimeOpt,
2751     // int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status);
2752     // with nonExistingTimeOpt=UCAL_TZ_LOCAL_LATTER and
2753     // duplicatedTimeOpt=UCAL_TZ_LOCAL_FORMER
2754     for (int m = 0; m < UPRV_LENGTHOF(DATES); m++) {
2755         status = U_ZERO_ERROR;
2756         ucal_setMillis(cal, MILLIS[m], &status);
2757         if (U_FAILURE(status)) {
2758             log_data_err("ucal_setMillis: %s\n", u_errorName(status));
2759         }
2760 
2761         ucal_getTimeZoneOffsetFromLocal(cal, UCAL_TZ_LOCAL_LATTER, UCAL_TZ_LOCAL_FORMER,
2762             &rawOffset, &dstOffset, &status);
2763         if (U_FAILURE(status)) {
2764             log_err("ERROR: ucal_getTimeZoneOffsetFromLocal((%d-%d-%d %d:%d:0),"
2765                     "UCAL_TZ_LOCAL_LATTER, UCAL_TZ_LOCAL_FORMER: %s\n",
2766                     DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4],
2767                     u_errorName(status));
2768         } else if (rawOffset != OFFSETS3[m][0] || dstOffset != OFFSETS3[m][1]) {
2769             log_err("Bad offset returned at (%d-%d-%d %d:%d:0) "
2770                     "(wall/UCAL_TZ_LOCAL_LATTER/UCAL_TZ_LOCAL_FORMER) \n- Got: %d / %d "
2771                     " Expected %d / %d\n",
2772                     DATES[m][0], DATES[m][1], DATES[m][2], DATES[m][3], DATES[m][4],
2773                     rawOffset, dstOffset, OFFSETS3[m][0], OFFSETS3[m][1]);
2774         }
2775     }
2776     ucal_close(cal);
2777 }
2778 
2779 #endif /* #if !UCONFIG_NO_FORMATTING */
2780