1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1997-2014, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  ********************************************************************/
6 /********************************************************************************
7 *
8 * File CDTDPTST.C
9 *
10 * Modification History:
11 *        Name                     Description
12 *     Madhu Katragadda               Creation
13 *********************************************************************************
14 */
15 /* INDEPTH TEST FOR DATE FORMAT */
16 
17 #include "unicode/utypes.h"
18 
19 #if !UCONFIG_NO_FORMATTING
20 
21 #include "unicode/uloc.h"
22 #include "unicode/udat.h"
23 #include "unicode/ucal.h"
24 #include "unicode/unum.h"
25 #include "unicode/ustring.h"
26 #include "cintltst.h"
27 #include "cdtdptst.h"
28 #include "cformtst.h"
29 
30 #include "cmemory.h"
31 
32 void addDtFrDepTest(TestNode** root);
33 
addDtFrDepTest(TestNode ** root)34 void addDtFrDepTest(TestNode** root)
35 {
36     addTest(root, &TestTwoDigitYearDSTParse, "tsformat/cdtdptst/TestTwoDigitYearDSTParse");
37     addTest(root, &TestPartialParse994, "tsformat/cdtdptst/TestPartialParse994");
38     addTest(root, &TestRunTogetherPattern985, "tsformat/cdtdptst/TestRunTogetherPattern985");
39     addTest(root, &TestCzechMonths459, "tsformat/cdtdptst/TestCzechMonths459");
40     addTest(root, &TestQuotePattern161, "tsformat/cdtdptst/TestQuotePattern161");
41     addTest(root, &TestBooleanAttributes, "tsformat/cdtdptst/TestBooleanAttributes");
42 
43 
44 }
45 
46 /**
47  * Test the parsing of 2-digit years.
48  */
TestTwoDigitYearDSTParse()49 void TestTwoDigitYearDSTParse()
50 {
51     UDateFormat *fullFmt, *fmt;
52     UErrorCode status = U_ZERO_ERROR;
53     UChar *pattern;
54     UDate d;
55     UChar *s;
56     int32_t pos;
57 
58     ctest_setTimeZone(NULL, &status);
59 
60     pattern=(UChar*)malloc(sizeof(UChar) * (strlen("EEE MMM dd HH:mm:ss.SSS zzz yyyy G")+1 ));
61     u_uastrcpy(pattern, "EEE MMM dd HH:mm:ss.SSS zzz yyyy G");
62     fullFmt= udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US",NULL,0,pattern, u_strlen(pattern),&status);
63     if(U_FAILURE(status))    {
64         log_data_err("FAIL: Error in creating a date format using udat_openPattern %s - (Are you missing data?)\n",
65             myErrorName(status) );
66     }
67     else {
68         log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n");
69 
70         u_uastrcpy(pattern, "dd-MMM-yy h:mm:ss 'o''clock' a z");
71         fmt= udat_open(UDAT_PATTERN,UDAT_PATTERN,"en_US", NULL, 0,pattern, u_strlen(pattern), &status);
72 
73 
74         s=(UChar*)malloc(sizeof(UChar) * (strlen("03-Apr-04 2:20:47 o'clock AM PST")+1) );
75         u_uastrcpy(s, "03-Apr-04 2:20:47 o'clock AM PST");
76         pos=0;
77         d = udat_parse(fmt, s, u_strlen(s), &pos, &status);
78         if (U_FAILURE(status)) {
79             log_err("FAIL: Could not parse \"%s\"\n", austrdup(s));
80         } else {
81             UCalendar *cal = ucal_open(NULL, 0, uloc_getDefault(), UCAL_TRADITIONAL, &status);
82             if (U_FAILURE(status)) {
83                 log_err_status(status, "FAIL: Could not open calendar: %s\n", u_errorName(status));
84             } else {
85                 int32_t h;
86                 ucal_setMillis(cal, d, &status);
87                 h = ucal_get(cal, UCAL_HOUR_OF_DAY, &status);
88                 if (U_FAILURE(status)) {
89                     log_err("FAIL: Some calendar operations failed");
90                 } else if (h != 2) {
91                     log_err("FAIL: Parse of \"%s\" returned HOUR_OF_DAY %d\n",
92                             austrdup(s), h);
93                 }
94                 ucal_close(cal);
95             }
96         }
97 
98         udat_close(fullFmt);
99         udat_close(fmt);
100         free(s);
101     }
102     free(pattern);
103 
104     ctest_resetTimeZone();
105 }
106 
107 
108 /**
109  * Verify that strings which contain incomplete specifications are parsed
110  * correctly.  In some instances, this means not being parsed at all, and
111  * returning an appropriate error.
112  */
TestPartialParse994()113 void TestPartialParse994()
114 {
115     int32_t pos;
116     UDateFormat *f;
117     UErrorCode status = U_ZERO_ERROR;
118     UChar *s;
119     UChar *fmtChars;
120     UDate d, null;
121     null=0;
122 
123     /* this is supposed to open default date format, but later on it treats it like it is "en_US"
124        - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
125     /* f = udat_open(UDAT_DEFAULT, UDAT_SHORT, NULL, NULL, 0, &status); */
126     f = udat_open(UDAT_DEFAULT, UDAT_SHORT, "en_US", NULL, 0,  NULL, 0,&status);
127     if(U_FAILURE(status)){
128         log_data_err("FAIL: ErrorCode received during test: %s (Are you missing data?)\n", myErrorName(status));
129         return;
130     }
131     s=(UChar*)malloc(sizeof(UChar) * (strlen("01/01/1997 10:11:42 AM")+1) );
132     u_uastrcpy(s, "01/01/1997 10:11:42 AM");
133     pos=0;
134     d = udat_parse(f, s, u_strlen(s), &pos, &status);
135     if(U_FAILURE(status)) {
136       log_data_err("FAIL: could not parse - exitting");
137       return;
138     }
139     fmtChars = myDateFormat(f, d);
140     if(fmtChars) {
141       log_verbose("%s\n", fmtChars);
142     } else {
143       log_data_err("FAIL: could not format \n");
144       return;
145     }
146     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10:11:42", d);
147     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10:", null);
148     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10", null);
149     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 ", null);
150     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01", null);
151     udat_close(f);
152     free(s);
153 }
154 
155 
156 
tryPat994(UDateFormat * format,const char * pattern,const char * s,UDate expected)157 void tryPat994(UDateFormat* format, const char* pattern, const char* s, UDate expected)
158 {
159     UChar *f;
160     UChar *str, *pat;
161     UDate date;
162     UDate null=0;
163     int32_t pos;
164     UErrorCode status = U_ZERO_ERROR;
165     str=(UChar*)malloc(sizeof(UChar) * (strlen(s) + 1) );
166     u_uastrcpy(str, s);
167     pat=(UChar*)malloc(sizeof(UChar) * (strlen(pattern) + 1) );
168     u_uastrcpy(pat, pattern);
169     log_verbose("Pattern : %s ;  String : %s\n", austrdup(pat), austrdup(str));
170     udat_applyPattern(format, FALSE, pat, u_strlen(pat));
171     pos=0;
172     date = udat_parse(format, str, u_strlen(str), &pos, &status);
173     if(U_FAILURE(status) || date == null) {
174         log_verbose("ParseException: : %s\n", myErrorName(status) );
175          if (expected != null)
176              log_err("FAIL: Expected: %s\n", austrdup(myDateFormat(format, expected)) );
177         }
178     else {
179         f=myDateFormat(format, date);
180         log_verbose(" parse( %s ) -> %s\n", austrdup(str), austrdup(f));
181         if (expected == null || date != expected)
182             log_err("FAIL: Expected null for \"%s\"\n", s);
183         if (u_strcmp(f, str) !=0)
184             log_err("FAIL: Expected : %s\n", austrdup(str) );
185     }
186 
187     free(str);
188     free(pat);
189 }
190 
191 
192 /**
193  * Verify the behavior of patterns in which digits for different fields run together
194  * without intervening separators.
195  */
TestRunTogetherPattern985()196 void TestRunTogetherPattern985()
197 {
198     int32_t pos;
199     UChar *pattern=NULL, *now=NULL, *then=NULL;
200     UDateFormat *format;
201     UDate date1, date2;
202     UErrorCode status = U_ZERO_ERROR;
203     pattern=(UChar*)malloc(sizeof(UChar) * (strlen("yyyyMMddHHmmssSSS")+1) );
204     u_uastrcpy(pattern, "yyyyMMddHHmmssSSS");
205     format = udat_open(UDAT_PATTERN, UDAT_PATTERN, NULL, NULL, 0,pattern, u_strlen(pattern), &status);
206     if(U_FAILURE(status)){
207         log_data_err("FAIL: Error in date format construction with pattern: %s - (Are you missing data?)\n", myErrorName(status));
208         return;
209     }
210     date1 = ucal_getNow();
211     now=myDateFormat(format, date1);
212     log_verbose("%s\n", austrdup(now) );
213     pos = 0;
214     date2 = udat_parse(format, now, u_strlen(now), &pos, &status);
215     if (date2 == 0) log_verbose("Parse stopped at : %d\n", pos);
216     else then=myDateFormat(format, date2);
217     log_verbose("%s\n", austrdup(then) );
218     if (!(date2 == date1)) log_err("FAIL\n");
219 
220     udat_close(format);
221     free(pattern);
222 
223 }
224 
225 /**
226  * Verify the handling of Czech June and July, which have the unique attribute that
227  * one is a proper prefix substring of the other.
228  */
TestCzechMonths459()229 void TestCzechMonths459()
230 {
231     int32_t lneed, pos;
232     UChar *pattern=NULL, *tzID=NULL;
233     UChar *juneStr, *julyStr;
234     UDateFormat *fmt;
235     UCalendar *cal;
236     UDate june, july, d;
237     UErrorCode status = U_ZERO_ERROR;
238     UChar *date;
239 
240     ctest_setTimeZone(NULL, &status);
241     fmt = udat_open(UDAT_FULL, UDAT_FULL, "cs", NULL, 0, NULL, 0, &status);
242     if(U_FAILURE(status)){
243         log_data_err("Error in constructing the date format -> %s (Are you missing data?)\n", u_errorName(status));
244         ctest_resetTimeZone();
245         return;
246     }
247     lneed=0;
248     lneed=udat_toPattern(fmt, TRUE, NULL, lneed, &status);
249     if(status==U_BUFFER_OVERFLOW_ERROR){
250         status=U_ZERO_ERROR;
251         pattern=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
252         udat_toPattern(fmt, TRUE, pattern, lneed+1, &status);
253     }
254     if(U_FAILURE(status)){ log_err("Error in extracting the pattern\n"); }
255     tzID=(UChar*)malloc(sizeof(UChar) * 4);
256     u_uastrcpy(tzID, "GMT");
257     cal=ucal_open(tzID, u_strlen(tzID), "cs", UCAL_GREGORIAN, &status);
258     if(U_FAILURE(status)){ log_err("error in ucal_open caldef : %s\n", myErrorName(status));    }
259 
260     ucal_setDate(cal, 1997, UCAL_JUNE, 15, &status);
261     june=ucal_getMillis(cal, &status);
262     ucal_setDate(cal, 1997, UCAL_JULY, 15, &status);
263     july=ucal_getMillis(cal, &status);
264 
265     juneStr = myDateFormat(fmt, june);
266     julyStr = myDateFormat(fmt, july);
267     pos=0;
268     if(juneStr == NULL) {
269       log_data_err("Can't load juneStr. Quitting.\n");
270       return;
271     }
272     d = udat_parse(fmt, juneStr, u_strlen(juneStr), &pos, &status);
273     date = myDateFormat(fmt, d);
274 
275     if(U_SUCCESS(status)){
276         UChar* out1 = myDateFormat(fmt, june);
277         UChar* out2 = myDateFormat(fmt, d);
278         if(u_strcmp(out1, out2) !=0)
279             log_err("Error in handling the czech month june\n");
280         else
281             log_verbose("Pass: Date = %s (czech month June)\n", aescstrdup(date, -1));
282     }else{
283         log_err("udat_parse failed. Error. %s\n",u_errorName(status));
284     }
285     pos=0;
286     d = udat_parse(fmt, julyStr, u_strlen(julyStr), &pos, &status);
287     date = myDateFormat(fmt, d);
288     if(u_strcmp(myDateFormat(fmt, july), myDateFormat(fmt, d) ) !=0)
289         log_err("Error in handling the czech month july\n");
290     else
291         log_verbose("Pass: Date = %s (czech month July)\n", aescstrdup(date, -1));
292 
293     ctest_resetTimeZone();
294     udat_close(fmt);
295     ucal_close(cal);
296     free(pattern);
297     free(tzID);
298 }
299 
300 /**
301  * Test the handling of single quotes in patterns.
302  */
TestQuotePattern161()303 void TestQuotePattern161()
304 {
305     UDateFormat *format;
306     UCalendar *cal;
307     UDate currentTime_1;
308     UChar *pattern, *tzID, *exp;
309     UChar *dateString;
310     UErrorCode status = U_ZERO_ERROR;
311     const char* expStr = "04/13/1999 at 10:42:28 AM ";
312 
313     ctest_setTimeZone(NULL, &status);
314 
315     pattern=(UChar*)malloc(sizeof(UChar) * (strlen("MM/dd/yyyy 'at' hh:mm:ss a zzz")+1) );
316     u_uastrcpy(pattern, "MM/dd/yyyy 'at' hh:mm:ss a zzz");
317 
318     /* this is supposed to open default date format, but later on it treats it like it is "en_US"
319        - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
320     /* format= udat_openPattern(pattern, u_strlen(pattern), NULL, &status); */
321     format= udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US", NULL, 0,pattern, u_strlen(pattern), &status);
322     if(U_FAILURE(status)){
323         log_data_err("error in udat_open: %s - (Are you missing data?)\n", myErrorName(status));
324         return;
325     }
326     tzID=(UChar*)malloc(sizeof(UChar) * 4);
327     u_uastrcpy(tzID, "PST");
328     /* this is supposed to open default date format, but later on it treats it like it is "en_US"
329        - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
330     /* cal=ucal_open(tzID, u_strlen(tzID), NULL, UCAL_TRADITIONAL, &status); */
331     cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status);
332     if(U_FAILURE(status)){ log_err("error in ucal_open cal : %s\n", myErrorName(status));    }
333 
334     ucal_setDateTime(cal, 1999, UCAL_APRIL, 13, 10, 42, 28, &status);
335     currentTime_1 = ucal_getMillis(cal, &status);
336 
337     dateString = myDateFormat(format, currentTime_1);
338     exp=(UChar*)malloc(sizeof(UChar) * (strlen(expStr) + 1) );
339     u_uastrcpy(exp, expStr);
340 
341     log_verbose("%s\n", austrdup(dateString) );
342     if(u_strncmp(dateString, exp, (int32_t)strlen(expStr)) !=0)
343         log_err("Error in formatting a pattern with single quotes\n");
344 
345     udat_close(format);
346     ucal_close(cal);
347     free(exp);
348     free(tzID);
349     free(pattern);
350 
351     ctest_resetTimeZone();
352 }
353 
354 /*
355  * Testing udat_getBooleanAttribute and  unum_setBooleanAttribute() to make sure basic C wrapper functionality is present
356  */
TestBooleanAttributes(void)357 void TestBooleanAttributes(void)
358 {
359     UDateFormat *en;
360     UErrorCode status=U_ZERO_ERROR;
361     UBool initialState = TRUE;
362     UBool switchedState = FALSE;
363 
364     log_verbose("\ncreating a date format with english locale\n");
365     en = udat_open(UDAT_FULL, UDAT_DEFAULT, "en_US", NULL, 0, NULL, 0, &status);
366     if(U_FAILURE(status)) {
367         log_data_err("error in creating the dateformat -> %s (Are you missing data?)\n",
368             myErrorName(status) );
369         return;
370     }
371 
372 
373     initialState = udat_getBooleanAttribute(en, UDAT_PARSE_ALLOW_NUMERIC, &status);
374     if(initialState != TRUE) switchedState = TRUE;  // if it wasn't the default of TRUE, then flip what we expect
375 
376     udat_setBooleanAttribute(en, UDAT_PARSE_ALLOW_NUMERIC, switchedState, &status);
377     if(switchedState != udat_getBooleanAttribute(en, UDAT_PARSE_ALLOW_NUMERIC, &status)) {
378         log_err("unable to switch states!");
379         return;
380     }
381 
382     udat_close(en);
383 }
384 
385 #endif /* #if !UCONFIG_NO_FORMATTING */
386