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