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
32void addDtFrDepTest(TestNode** root);
33
34void 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 */
49void 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 */
113void 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
157void 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 */
196void 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 */
229void 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 */
303void 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 */
357void 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