// © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /******************************************************************** * COPYRIGHT: * Copyright (c) 1997-2014, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ /******************************************************************************** * * File CDTDPTST.C * * Modification History: * Name Description * Madhu Katragadda Creation ********************************************************************************* */ /* INDEPTH TEST FOR DATE FORMAT */ #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING #include "unicode/uloc.h" #include "unicode/udat.h" #include "unicode/ucal.h" #include "unicode/unum.h" #include "unicode/ustring.h" #include "cintltst.h" #include "cdtdptst.h" #include "cformtst.h" #include "cmemory.h" void addDtFrDepTest(TestNode** root); void addDtFrDepTest(TestNode** root) { addTest(root, &TestTwoDigitYearDSTParse, "tsformat/cdtdptst/TestTwoDigitYearDSTParse"); addTest(root, &TestPartialParse994, "tsformat/cdtdptst/TestPartialParse994"); addTest(root, &TestRunTogetherPattern985, "tsformat/cdtdptst/TestRunTogetherPattern985"); addTest(root, &TestCzechMonths459, "tsformat/cdtdptst/TestCzechMonths459"); addTest(root, &TestQuotePattern161, "tsformat/cdtdptst/TestQuotePattern161"); addTest(root, &TestBooleanAttributes, "tsformat/cdtdptst/TestBooleanAttributes"); } /** * Test the parsing of 2-digit years. */ void TestTwoDigitYearDSTParse() { UDateFormat *fullFmt, *fmt; UErrorCode status = U_ZERO_ERROR; UChar *pattern; UDate d; UChar *s; int32_t pos; ctest_setTimeZone(NULL, &status); pattern=(UChar*)malloc(sizeof(UChar) * (strlen("EEE MMM dd HH:mm:ss.SSS zzz yyyy G")+1 )); u_uastrcpy(pattern, "EEE MMM dd HH:mm:ss.SSS zzz yyyy G"); fullFmt= udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US",NULL,0,pattern, u_strlen(pattern),&status); if(U_FAILURE(status)) { log_data_err("FAIL: Error in creating a date format using udat_openPattern %s - (Are you missing data?)\n", myErrorName(status) ); } else { log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n"); u_uastrcpy(pattern, "dd-MMM-yy h:mm:ss 'o''clock' a z"); fmt= udat_open(UDAT_PATTERN,UDAT_PATTERN,"en_US", NULL, 0,pattern, u_strlen(pattern), &status); s=(UChar*)malloc(sizeof(UChar) * (strlen("03-Apr-04 2:20:47 o'clock AM PST")+1) ); u_uastrcpy(s, "03-Apr-04 2:20:47 o'clock AM PST"); pos=0; d = udat_parse(fmt, s, u_strlen(s), &pos, &status); if (U_FAILURE(status)) { log_err("FAIL: Could not parse \"%s\"\n", austrdup(s)); } else { UCalendar *cal = ucal_open(NULL, 0, uloc_getDefault(), UCAL_TRADITIONAL, &status); if (U_FAILURE(status)) { log_err_status(status, "FAIL: Could not open calendar: %s\n", u_errorName(status)); } else { int32_t h; ucal_setMillis(cal, d, &status); h = ucal_get(cal, UCAL_HOUR_OF_DAY, &status); if (U_FAILURE(status)) { log_err("FAIL: Some calendar operations failed"); } else if (h != 2) { log_err("FAIL: Parse of \"%s\" returned HOUR_OF_DAY %d\n", austrdup(s), h); } ucal_close(cal); } } udat_close(fullFmt); udat_close(fmt); free(s); } free(pattern); ctest_resetTimeZone(); } /** * Verify that strings which contain incomplete specifications are parsed * correctly. In some instances, this means not being parsed at all, and * returning an appropriate error. */ void TestPartialParse994() { int32_t pos; UDateFormat *f; UErrorCode status = U_ZERO_ERROR; UChar *s; UChar *fmtChars; UDate d, null; null=0; /* this is supposed to open default date format, but later on it treats it like it is "en_US" - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ /* f = udat_open(UDAT_DEFAULT, UDAT_SHORT, NULL, NULL, 0, &status); */ f = udat_open(UDAT_DEFAULT, UDAT_SHORT, "en_US", NULL, 0, NULL, 0,&status); if(U_FAILURE(status)){ log_data_err("FAIL: ErrorCode received during test: %s (Are you missing data?)\n", myErrorName(status)); return; } s=(UChar*)malloc(sizeof(UChar) * (strlen("01/01/1997 10:11:42 AM")+1) ); u_uastrcpy(s, "01/01/1997 10:11:42 AM"); pos=0; d = udat_parse(f, s, u_strlen(s), &pos, &status); if(U_FAILURE(status)) { log_data_err("FAIL: could not parse - exitting"); return; } fmtChars = myDateFormat(f, d); if(fmtChars) { log_verbose("%s\n", fmtChars); } else { log_data_err("FAIL: could not format \n"); return; } tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10:11:42", d); tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10:", null); tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10", null); tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 ", null); tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01", null); udat_close(f); free(s); } void tryPat994(UDateFormat* format, const char* pattern, const char* s, UDate expected) { UChar *f; UChar *str, *pat; UDate date; UDate null=0; int32_t pos; UErrorCode status = U_ZERO_ERROR; str=(UChar*)malloc(sizeof(UChar) * (strlen(s) + 1) ); u_uastrcpy(str, s); pat=(UChar*)malloc(sizeof(UChar) * (strlen(pattern) + 1) ); u_uastrcpy(pat, pattern); log_verbose("Pattern : %s ; String : %s\n", austrdup(pat), austrdup(str)); udat_applyPattern(format, FALSE, pat, u_strlen(pat)); pos=0; date = udat_parse(format, str, u_strlen(str), &pos, &status); if(U_FAILURE(status) || date == null) { log_verbose("ParseException: : %s\n", myErrorName(status) ); if (expected != null) log_err("FAIL: Expected: %s\n", austrdup(myDateFormat(format, expected)) ); } else { f=myDateFormat(format, date); log_verbose(" parse( %s ) -> %s\n", austrdup(str), austrdup(f)); if (expected == null || date != expected) log_err("FAIL: Expected null for \"%s\"\n", s); if (u_strcmp(f, str) !=0) log_err("FAIL: Expected : %s\n", austrdup(str) ); } free(str); free(pat); } /** * Verify the behavior of patterns in which digits for different fields run together * without intervening separators. */ void TestRunTogetherPattern985() { int32_t pos; UChar *pattern=NULL, *now=NULL, *then=NULL; UDateFormat *format; UDate date1, date2; UErrorCode status = U_ZERO_ERROR; pattern=(UChar*)malloc(sizeof(UChar) * (strlen("yyyyMMddHHmmssSSS")+1) ); u_uastrcpy(pattern, "yyyyMMddHHmmssSSS"); format = udat_open(UDAT_PATTERN, UDAT_PATTERN, NULL, NULL, 0,pattern, u_strlen(pattern), &status); if(U_FAILURE(status)){ log_data_err("FAIL: Error in date format construction with pattern: %s - (Are you missing data?)\n", myErrorName(status)); free(pattern); return; } date1 = ucal_getNow(); now=myDateFormat(format, date1); log_verbose("%s\n", austrdup(now) ); pos = 0; date2 = udat_parse(format, now, u_strlen(now), &pos, &status); if (date2 == 0) log_verbose("Parse stopped at : %d\n", pos); else then=myDateFormat(format, date2); log_verbose("%s\n", austrdup(then) ); if (!(date2 == date1)) log_err("FAIL\n"); udat_close(format); free(pattern); } /** * Verify the handling of Czech June and July, which have the unique attribute that * one is a proper prefix substring of the other. */ void TestCzechMonths459() { int32_t lneed, pos; UChar *pattern=NULL, *tzID=NULL; UChar *juneStr, *julyStr; UDateFormat *fmt; UCalendar *cal; UDate june, july, d; UErrorCode status = U_ZERO_ERROR; UChar *date; ctest_setTimeZone(NULL, &status); fmt = udat_open(UDAT_FULL, UDAT_FULL, "cs", NULL, 0, NULL, 0, &status); if(U_FAILURE(status)){ log_data_err("Error in constructing the date format -> %s (Are you missing data?)\n", u_errorName(status)); ctest_resetTimeZone(); return; } lneed=0; lneed=udat_toPattern(fmt, TRUE, NULL, lneed, &status); if(status==U_BUFFER_OVERFLOW_ERROR){ status=U_ZERO_ERROR; pattern=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); udat_toPattern(fmt, TRUE, pattern, lneed+1, &status); } if(U_FAILURE(status)){ log_err("Error in extracting the pattern\n"); } tzID=(UChar*)malloc(sizeof(UChar) * 4); u_uastrcpy(tzID, "GMT"); cal=ucal_open(tzID, u_strlen(tzID), "cs", UCAL_GREGORIAN, &status); if(U_FAILURE(status)){ log_err("error in ucal_open caldef : %s\n", myErrorName(status)); } ucal_setDate(cal, 1997, UCAL_JUNE, 15, &status); june=ucal_getMillis(cal, &status); ucal_setDate(cal, 1997, UCAL_JULY, 15, &status); july=ucal_getMillis(cal, &status); juneStr = myDateFormat(fmt, june); julyStr = myDateFormat(fmt, july); pos=0; if(juneStr == NULL) { log_data_err("Can't load juneStr. Quitting.\n"); return; } d = udat_parse(fmt, juneStr, u_strlen(juneStr), &pos, &status); date = myDateFormat(fmt, d); if(U_SUCCESS(status)){ UChar* out1 = myDateFormat(fmt, june); UChar* out2 = myDateFormat(fmt, d); if(u_strcmp(out1, out2) !=0) log_err("Error in handling the czech month june\n"); else log_verbose("Pass: Date = %s (czech month June)\n", aescstrdup(date, -1)); }else{ log_err("udat_parse failed. Error. %s\n",u_errorName(status)); } pos=0; d = udat_parse(fmt, julyStr, u_strlen(julyStr), &pos, &status); date = myDateFormat(fmt, d); if(u_strcmp(myDateFormat(fmt, july), myDateFormat(fmt, d) ) !=0) log_err("Error in handling the czech month july\n"); else log_verbose("Pass: Date = %s (czech month July)\n", aescstrdup(date, -1)); ctest_resetTimeZone(); udat_close(fmt); ucal_close(cal); free(pattern); free(tzID); } /** * Test the handling of single quotes in patterns. */ void TestQuotePattern161() { UDateFormat *format = NULL; UCalendar *cal = NULL; UDate currentTime_1; UChar *pattern = NULL; UChar *tzID = NULL; UChar *exp = NULL; UChar *dateString; UErrorCode status = U_ZERO_ERROR; const char* expStr = "04/13/1999 at 10:42:28 AM "; ctest_setTimeZone(NULL, &status); pattern=(UChar*)malloc(sizeof(UChar) * (strlen("MM/dd/yyyy 'at' hh:mm:ss a zzz")+1) ); u_uastrcpy(pattern, "MM/dd/yyyy 'at' hh:mm:ss a zzz"); /* this is supposed to open default date format, but later on it treats it like it is "en_US" - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ /* format= udat_openPattern(pattern, u_strlen(pattern), NULL, &status); */ format= udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US", NULL, 0,pattern, u_strlen(pattern), &status); if(U_FAILURE(status)){ log_data_err("error in udat_open: %s - (Are you missing data?)\n", myErrorName(status)); } else { tzID=(UChar*)malloc(sizeof(UChar) * 4); u_uastrcpy(tzID, "PST"); /* this is supposed to open default date format, but later on it treats it like it is "en_US" - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ /* cal=ucal_open(tzID, u_strlen(tzID), NULL, UCAL_TRADITIONAL, &status); */ cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); if(U_FAILURE(status)){ log_err("error in ucal_open cal : %s\n", myErrorName(status)); } ucal_setDateTime(cal, 1999, UCAL_APRIL, 13, 10, 42, 28, &status); currentTime_1 = ucal_getMillis(cal, &status); dateString = myDateFormat(format, currentTime_1); exp=(UChar*)malloc(sizeof(UChar) * (strlen(expStr) + 1) ); u_uastrcpy(exp, expStr); log_verbose("%s\n", austrdup(dateString) ); if(u_strncmp(dateString, exp, (int32_t)strlen(expStr)) !=0) { log_err("Error in formatting a pattern with single quotes\n"); } } udat_close(format); ucal_close(cal); free(exp); free(tzID); free(pattern); ctest_resetTimeZone(); } /* * Testing udat_getBooleanAttribute and unum_setBooleanAttribute() to make sure basic C wrapper functionality is present */ void TestBooleanAttributes(void) { UDateFormat *en; UErrorCode status=U_ZERO_ERROR; UBool initialState = TRUE; UBool switchedState = FALSE; log_verbose("\ncreating a date format with english locale\n"); en = udat_open(UDAT_FULL, UDAT_DEFAULT, "en_US", NULL, 0, NULL, 0, &status); if(U_FAILURE(status)) { log_data_err("error in creating the dateformat -> %s (Are you missing data?)\n", myErrorName(status) ); return; } initialState = udat_getBooleanAttribute(en, UDAT_PARSE_ALLOW_NUMERIC, &status); if(initialState != TRUE) switchedState = TRUE; // if it wasn't the default of TRUE, then flip what we expect udat_setBooleanAttribute(en, UDAT_PARSE_ALLOW_NUMERIC, switchedState, &status); if(switchedState != udat_getBooleanAttribute(en, UDAT_PARSE_ALLOW_NUMERIC, &status)) { log_err("unable to switch states!"); return; } udat_close(en); } #endif /* #if !UCONFIG_NO_FORMATTING */