/** call-seq: * calendar.format(pattern = nil , locale = nil) * * Formats this calendar time using given pattern and locale. Returns UString or nil on failure. * Valid value types for pattern are: * nil - long format for date and time * UString - specification of format, as defined in docs/FORMATTING * Symbol - one of :short, :medium, :long, :full, :none , sets format for both date and time * Hash - {:time => aSymbol, :date => aSymbol} - sets separate formats for date and time, valid symbols see above */ VALUE icu4r_cal_format(int argc, VALUE * argv, VALUE obj) { UErrorCode status = U_ZERO_ERROR; UDateFormat * format; UDate time_to_format; UChar * buf = NULL, * pattern = NULL; long capa = 0, pattern_len = 0; char *locale = NULL; VALUE loc, pat, ret = Qnil; int n , def_d_format = UDAT_FULL, def_t_format = UDAT_FULL; n = rb_scan_args(argc, argv, "02", &pat, &loc); if( n == 2) { Check_Type(loc, T_STRING); locale = RSTRING_PTR(loc); } if (n >= 1 && pat != Qnil) { switch(TYPE(pat)) { case T_SYMBOL: def_d_format = def_t_format = icu4r_get_cal_format_int(pat); break; case T_HASH: def_d_format = icu4r_get_cal_format_int(rb_hash_aref(pat, ID2SYM(rb_intern("date")))); def_t_format = icu4r_get_cal_format_int(rb_hash_aref(pat, ID2SYM(rb_intern("time")))); break; default: Check_Class(pat, rb_cUString); pattern = ICU_PTR(pat); pattern_len = ICU_LEN(pat); break; } } format = udat_open(def_t_format, def_d_format, locale, NULL, 0, NULL, 0, &status); if( pattern ) { udat_applyPattern(format, 0, pattern, pattern_len); } ICU_RAISE(status); udat_setCalendar(format, UCALENDAR(obj)); time_to_format = ucal_getMillis(UCALENDAR(obj), &status); capa = udat_format(format, time_to_format, buf, capa, NULL, &status); if( U_BUFFER_OVERFLOW_ERROR == status) { buf = ALLOC_N(UChar, capa+1); status = U_ZERO_ERROR; capa = udat_format(format, time_to_format, buf, capa, NULL, &status); ret = icu_ustr_new_set(buf, capa, capa+1); } udat_close(format); ICU_RAISE(status); return ret; }
/* Testing the DateFormat API */ static void TestDateFormat() { UDateFormat *def, *fr, *it, *de, *def1, *fr_pat; UDateFormat *any; UDateFormat *copy; UErrorCode status = U_ZERO_ERROR; UChar* result = NULL; const UCalendar *cal; const UNumberFormat *numformat1, *numformat2; UChar temp[50]; int32_t numlocales; UDate d1; int i; int32_t resultlength; int32_t resultlengthneeded; int32_t parsepos; UDate d = 837039928046.0; double num = -10456.37; /*const char* str="yyyy.MM.dd G 'at' hh:mm:ss z"; const char t[]="2/3/76 2:50 AM";*/ /*Testing udat_open() to open a dateformat */ ctest_setTimeZone(NULL, &status); log_verbose("\nTesting udat_open() with various parameters\n"); fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL,0, NULL, 0,&status); if(U_FAILURE(status)) { log_data_err("FAIL: error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n", myErrorName(status) ); return; } /* 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" */ /* def = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0, &status); */ def = udat_open(UDAT_SHORT, UDAT_SHORT, "en_US", NULL, 0,NULL, 0, &status); if(U_FAILURE(status)) { log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n", myErrorName(status) ); return; } it = udat_open(UDAT_DEFAULT, UDAT_MEDIUM, "it_IT", NULL, 0, NULL, 0,&status); if(U_FAILURE(status)) { log_err("FAIL: error in creating the dateformat using medium date style with italian locale\n %s\n", myErrorName(status) ); return; } de = udat_open(UDAT_LONG, UDAT_LONG, "de_DE", NULL, 0, NULL, 0,&status); if(U_FAILURE(status)) { log_err("FAIL: error in creating the dateformat using long time and date styles with german locale\n %s\n", myErrorName(status)); return; } /*creating a default dateformat */ def1 = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0,NULL, 0, &status); if(U_FAILURE(status)) { log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n", myErrorName(status) ); return; } /*Testing udat_getAvailable() and udat_countAvailable()*/ log_verbose("\nTesting getAvailableLocales and countAvailable()\n"); numlocales=udat_countAvailable(); /* use something sensible w/o hardcoding the count */ if(numlocales < 0) log_data_err("FAIL: error in countAvailable\n"); log_verbose("The number of locales for which date/time formatting patterns are available is %d\n", numlocales); for(i=0;i<numlocales;i++) { UErrorCode subStatus = U_ZERO_ERROR; log_verbose("Testing open of %s\n", udat_getAvailable(i)); any = udat_open(UDAT_SHORT, UDAT_SHORT, udat_getAvailable(i), NULL ,0, NULL, 0, &subStatus); if(U_FAILURE(subStatus)) { log_data_err("FAIL: date format %s (getAvailable(%d)) is not instantiable: %s\n", udat_getAvailable(i), i, u_errorName(subStatus)); } udat_close(any); } /*Testing udat_clone()*/ log_verbose("\nTesting the udat_clone() function of date format\n"); copy=udat_clone(def, &status); if(U_FAILURE(status)){ log_err("Error in creating the clone using udat_clone: %s\n", myErrorName(status) ); } /*if(def != copy) log_err("Error in udat_clone");*/ /*how should i check for equality???? */ /*Testing udat_format()*/ log_verbose("\nTesting the udat_format() function of date format\n"); u_uastrcpy(temp, "7/10/96 4:05 PM"); /*format using def */ resultlength=0; resultlengthneeded=udat_format(def, d, NULL, resultlength, NULL, &status); if(status==U_BUFFER_OVERFLOW_ERROR) { status=U_ZERO_ERROR; resultlength=resultlengthneeded+1; if(result != NULL) { free(result); result = NULL; } result=(UChar*)malloc(sizeof(UChar) * resultlength); udat_format(def, d, result, resultlength, NULL, &status); } if(U_FAILURE(status) || !result) { log_err("FAIL: Error in formatting using udat_format(.....) %s\n", myErrorName(status) ); return; } else log_verbose("PASS: formatting successful\n"); if(u_strcmp(result, temp)==0) log_verbose("PASS: Date Format for US locale successful using udat_format()\n"); else { char xbuf[2048]; char gbuf[2048]; u_austrcpy(xbuf, temp); u_austrcpy(gbuf, result); log_err("FAIL: Date Format for US locale failed using udat_format() - expected %s got %s\n", xbuf, gbuf); } /*format using fr */ u_unescape("10 juil. 1996 16:05:28 heure avanc\\u00E9e du Pacifique", temp, 50); if(result != NULL) { free(result); result = NULL; } result=myDateFormat(fr, d); if(u_strcmp(result, temp)==0) log_verbose("PASS: Date Format for french locale successful using udat_format()\n"); else log_data_err("FAIL: Date Format for french locale failed using udat_format().\n" ); /*format using it */ u_uastrcpy(temp, "10/lug/1996 16:05:28"); { UChar *fmtted; char g[100]; char x[100]; fmtted = myDateFormat(it,d); u_austrcpy(g, fmtted); u_austrcpy(x, temp); if(u_strcmp(fmtted, temp)==0) { log_verbose("PASS: Date Format for italian locale successful uisng udat_format() - wanted %s, got %s\n", x, g); } else { log_data_err("FAIL: Date Format for italian locale failed using udat_format() - wanted %s, got %s\n", x, g); } } /*Testing parsing using udat_parse()*/ log_verbose("\nTesting parsing using udat_parse()\n"); u_uastrcpy(temp,"2/3/76 2:50 AM"); parsepos=0; status=U_ZERO_ERROR; d1=udat_parse(def, temp, u_strlen(temp), &parsepos, &status); if(U_FAILURE(status)) { log_err("FAIL: Error in parsing using udat_parse(.....) %s\n", myErrorName(status) ); } else log_verbose("PASS: parsing succesful\n"); /*format it back and check for equality */ if(u_strcmp(myDateFormat(def, d1),temp)!=0) log_err("FAIL: error in parsing\n"); /*Testing parsing using udat_parse()*/ log_verbose("\nTesting parsing using udat_parse()\n"); u_uastrcpy(temp,"2/Don't parse this part"); status=U_ZERO_ERROR; d1=udat_parse(def, temp, u_strlen(temp), NULL, &status); if(status != U_PARSE_ERROR) { log_err("FAIL: udat_parse(\"bad string\") passed when it should have failed\n"); } else log_verbose("PASS: parsing succesful\n"); /*Testing udat_openPattern() */ status=U_ZERO_ERROR; log_verbose("\nTesting the udat_openPattern with a specified pattern\n"); /*for french locale */ fr_pat=udat_open(UDAT_IGNORE, UDAT_IGNORE,"fr_FR",NULL,0,temp, u_strlen(temp), &status); if(U_FAILURE(status)) { log_err("FAIL: Error in creating a date format using udat_openPattern \n %s\n", myErrorName(status) ); } else log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n"); /*Testing applyPattern and toPattern */ log_verbose("\nTesting applyPattern and toPattern()\n"); udat_applyPattern(def1, FALSE, temp, u_strlen(temp)); log_verbose("Extracting the pattern\n"); resultlength=0; resultlengthneeded=udat_toPattern(def1, FALSE, NULL, resultlength, &status); if(status==U_BUFFER_OVERFLOW_ERROR) { status=U_ZERO_ERROR; resultlength=resultlengthneeded + 1; result=(UChar*)malloc(sizeof(UChar) * resultlength); udat_toPattern(def1, FALSE, result, resultlength, &status); } if(U_FAILURE(status)) { log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n", myErrorName(status) ); } if(u_strcmp(result, temp)!=0) log_err("FAIL: Error in extracting the pattern\n"); else log_verbose("PASS: applyPattern and toPattern work fine\n"); if(result != NULL) { free(result); result = NULL; } /*Testing getter and setter functions*/ /*isLenient and setLenient()*/ log_verbose("\nTesting the isLenient and setLenient properties\n"); udat_setLenient(fr, udat_isLenient(it)); if(udat_isLenient(fr) != udat_isLenient(it)) log_err("ERROR: setLenient() failed\n"); else log_verbose("PASS: setLenient() successful\n"); /*Test get2DigitYearStart set2DigitYearStart */ log_verbose("\nTesting the get and set 2DigitYearStart properties\n"); d1= udat_get2DigitYearStart(fr_pat,&status); if(U_FAILURE(status)) { log_err("ERROR: udat_get2DigitYearStart failed %s\n", myErrorName(status) ); } status = U_ZERO_ERROR; udat_set2DigitYearStart(def1 ,d1, &status); if(U_FAILURE(status)) { log_err("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) ); } if(udat_get2DigitYearStart(fr_pat, &status) != udat_get2DigitYearStart(def1, &status)) log_err("FAIL: error in set2DigitYearStart\n"); else log_verbose("PASS: set2DigitYearStart successful\n"); /*try setting it to another value */ udat_set2DigitYearStart(de, 2000.0, &status); if(U_FAILURE(status)){ log_verbose("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) ); } if(udat_get2DigitYearStart(de, &status) != 2000) log_err("FAIL: error in set2DigitYearStart\n"); else log_verbose("PASS: set2DigitYearStart successful\n"); /*Test getNumberFormat() and setNumberFormat() */ log_verbose("\nTesting the get and set NumberFormat properties of date format\n"); numformat1=udat_getNumberFormat(fr_pat); udat_setNumberFormat(def1, numformat1); numformat2=udat_getNumberFormat(def1); if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0) log_err("FAIL: error in setNumberFormat or getNumberFormat()\n"); else log_verbose("PASS:setNumberFormat and getNumberFormat succesful\n"); /*try setting the number format to another format */ numformat1=udat_getNumberFormat(def); udat_setNumberFormat(def1, numformat1); numformat2=udat_getNumberFormat(def1); if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0) log_err("FAIL: error in setNumberFormat or getNumberFormat()\n"); else log_verbose("PASS: setNumberFormat and getNumberFormat succesful\n"); /*Test getCalendar and setCalendar*/ log_verbose("\nTesting the udat_getCalendar() and udat_setCalendar() properties\n"); cal=udat_getCalendar(fr_pat); udat_setCalendar(def1, cal); if(!ucal_equivalentTo(udat_getCalendar(fr_pat), udat_getCalendar(def1))) log_err("FAIL: Error in setting and getting the calendar\n"); else log_verbose("PASS: getting and setting calendar successful\n"); if(result!=NULL) { free(result); } /*Closing the UDateForamt */ udat_close(def); udat_close(fr); udat_close(it); udat_close(de); udat_close(def1); udat_close(fr_pat); udat_close(copy); ctest_resetTimeZone(); }
/* Function: EnumSymbols Enumerates all of the symbols of a type for a locale and calendar and invokes a callback for each value. */ static int32_t EnumSymbols(const char* locale, CalendarId calendarId, UDateFormatSymbolType type, int32_t startIndex, EnumCalendarInfoCallback callback, const void* context) { UErrorCode err = U_ZERO_ERROR; UDateFormat* pFormat = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, locale, NULL, 0, NULL, 0, &err); if (U_FAILURE(err)) return FALSE; char localeWithCalendarName[ULOC_FULLNAME_CAPACITY]; strncpy(localeWithCalendarName, locale, ULOC_FULLNAME_CAPACITY); uloc_setKeywordValue("calendar", GetCalendarName(calendarId), localeWithCalendarName, ULOC_FULLNAME_CAPACITY, &err); UCalendar* pCalendar = ucal_open(NULL, 0, localeWithCalendarName, UCAL_DEFAULT, &err); if (U_FAILURE(err)) { udat_close(pFormat); return FALSE; } udat_setCalendar(pFormat, pCalendar); int32_t symbolCount = udat_countSymbols(pFormat, type); UChar stackSymbolBuf[100]; UChar* symbolBuf; for (int32_t i = startIndex; U_SUCCESS(err) && i < symbolCount; i++) { UErrorCode ignore = U_ZERO_ERROR; int symbolLen = udat_getSymbols(pFormat, type, i, NULL, 0, &ignore) + 1; if (symbolLen <= sizeof(stackSymbolBuf) / sizeof(stackSymbolBuf[0])) { symbolBuf = stackSymbolBuf; } else { symbolBuf = calloc(symbolLen, sizeof(UChar)); if (symbolBuf == NULL) { err = U_MEMORY_ALLOCATION_ERROR; break; } } udat_getSymbols(pFormat, type, i, symbolBuf, symbolLen, &err); if (U_SUCCESS(err)) { callback(symbolBuf, context); } if (symbolBuf != stackSymbolBuf) { free(symbolBuf); } } udat_close(pFormat); ucal_close(pCalendar); return UErrorCodeToBool(err); }
/* {{{ */ static void datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) { char* locale; int locale_len = 0; zval* object; long date_type = 0; long time_type = 0; long calendar = UCAL_GREGORIAN; char* timezone_str = NULL; int timezone_str_len = 0; char* pattern_str = NULL; int pattern_str_len = 0; UChar* svalue = NULL; /* UTF-16 pattern_str */ int slength = 0; UChar* timezone_utf16 = NULL; /* UTF-16 timezone_str */ int timezone_utf16_len = 0; UCalendar ucal_obj = NULL; IntlDateFormatter_object* dfo; intl_error_reset( NULL TSRMLS_CC ); object = return_value; /* Parse parameters. */ if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "sll|sls", &locale, &locale_len, &date_type, &time_type, &timezone_str, &timezone_str_len, &calendar,&pattern_str, &pattern_str_len ) == FAILURE ) { intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: unable to parse input parameters", 0 TSRMLS_CC ); zval_dtor(return_value); RETURN_NULL(); } INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value); if (calendar != UCAL_TRADITIONAL && calendar != UCAL_GREGORIAN) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: " "invalid value for calendar type; it must be one of " "IntlDateFormatter::TRADITIONAL (locale's default calendar) " "or IntlDateFormatter::GREGORIAN", 0 TSRMLS_CC); goto error; } DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; if (DATE_FORMAT_OBJECT(dfo) != NULL) { intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: cannot call constructor twice", 0 TSRMLS_CC); return; } /* Convert pattern (if specified) to UTF-16. */ if( pattern_str && pattern_str_len>0 ){ intl_convert_utf8_to_utf16(&svalue, &slength, pattern_str, pattern_str_len, &INTL_DATA_ERROR_CODE(dfo)); if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { /* object construction -> only set global error */ intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: " "error converting pattern to UTF-16", 0 TSRMLS_CC); goto error; } } /* resources allocated from now on */ /* Convert pattern (if specified) to UTF-16. */ if( timezone_str && timezone_str_len >0 ){ intl_convert_utf8_to_utf16(&timezone_utf16, &timezone_utf16_len, timezone_str, timezone_str_len, &INTL_DATA_ERROR_CODE(dfo)); if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: " "error converting timezone_str to UTF-16", 0 TSRMLS_CC); goto error; } } if(locale_len == 0) { locale = INTL_G(default_locale); } if( pattern_str && pattern_str_len>0 ){ DATE_FORMAT_OBJECT(dfo) = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale, timezone_utf16, timezone_utf16_len, svalue, slength, &INTL_DATA_ERROR_CODE(dfo)); } else { DATE_FORMAT_OBJECT(dfo) = udat_open(time_type, date_type, locale, timezone_utf16, timezone_utf16_len, svalue, slength, &INTL_DATA_ERROR_CODE(dfo)); } if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { if (calendar != UCAL_TRADITIONAL) { ucal_obj = ucal_open(timezone_utf16, timezone_utf16_len, locale, calendar, &INTL_DATA_ERROR_CODE(dfo)); if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { udat_setCalendar(DATE_FORMAT_OBJECT(dfo), ucal_obj); ucal_close(ucal_obj); } else { intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create" ": error opening calendar", 0 TSRMLS_CC); goto error; } } } else { intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: date " "formatter creation failed", 0 TSRMLS_CC); goto error; } /* Set the class variables */ dfo->date_type = date_type; dfo->time_type = time_type; dfo->calendar = calendar; if( timezone_str && timezone_str_len > 0){ dfo->timezone_id = estrndup( timezone_str, timezone_str_len); } error: if (svalue) { efree(svalue); } if (timezone_utf16) { efree(timezone_utf16); } if (U_FAILURE(intl_error_get_code(NULL TSRMLS_CC))) { /* free_object handles partially constructed instances fine */ zval_dtor(return_value); RETVAL_NULL(); } }