U_CFUNC PHP_FUNCTION(datefmt_format_object) { zval *object, *format = NULL; const char *locale_str = NULL; size_t locale_len; bool pattern = false; UDate date; TimeZone *timeZone = NULL; UErrorCode status = U_ZERO_ERROR; DateFormat *df = NULL; Calendar *cal = NULL; DateFormat::EStyle dateStyle = DateFormat::kDefault, timeStyle = DateFormat::kDefault; if (zend_parse_parameters(ZEND_NUM_ARGS(), "o|zs!", &object, &format, &locale_str, &locale_len) == FAILURE) { RETURN_FALSE; } if (!locale_str) { locale_str = intl_locale_get_default(); } if (format == NULL || Z_TYPE_P(format) == IS_NULL) { //nothing } else if (Z_TYPE_P(format) == IS_ARRAY) { HashTable *ht = Z_ARRVAL_P(format); HashPosition pos = {0}; zval *z; if (zend_hash_num_elements(ht) != 2) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format_object: bad format; if array, it must have " "two elements", 0); RETURN_FALSE; } zend_hash_internal_pointer_reset_ex(ht, &pos); z = zend_hash_get_current_data_ex(ht, &pos); if (!valid_format(z)) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format_object: bad format; the date format (first " "element of the array) is not valid", 0); RETURN_FALSE; } dateStyle = (DateFormat::EStyle)Z_LVAL_P(z); zend_hash_move_forward_ex(ht, &pos); z = zend_hash_get_current_data_ex(ht, &pos); if (!valid_format(z)) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format_object: bad format; the time format (" "second element of the array) is not valid", 0); RETURN_FALSE; } timeStyle = (DateFormat::EStyle)Z_LVAL_P(z); } else if (Z_TYPE_P(format) == IS_LONG) { if (!valid_format(format)) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format_object: the date/time format type is invalid", 0); RETURN_FALSE; } dateStyle = timeStyle = (DateFormat::EStyle)Z_LVAL_P(format); } else { convert_to_string_ex(format); if (Z_STRLEN_P(format) == 0) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format_object: the format is empty", 0); RETURN_FALSE; } pattern = true; } //there's no support for relative time in ICU yet timeStyle = (DateFormat::EStyle)(timeStyle & ~DateFormat::kRelative); zend_class_entry *instance_ce = Z_OBJCE_P(object); if (instanceof_function(instance_ce, Calendar_ce_ptr)) { Calendar *obj_cal = calendar_fetch_native_calendar(object); if (obj_cal == NULL) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format_object: bad IntlCalendar instance: " "not initialized properly", 0); RETURN_FALSE; } timeZone = obj_cal->getTimeZone().clone(); date = obj_cal->getTime(status); if (U_FAILURE(status)) { intl_error_set(NULL, status, "datefmt_format_object: error obtaining instant from " "IntlCalendar", 0); RETVAL_FALSE; goto cleanup; } cal = obj_cal->clone(); } else if (instanceof_function(instance_ce, php_date_get_date_ce())) { if (intl_datetime_decompose(object, &date, &timeZone, NULL, "datefmt_format_object") == FAILURE) { RETURN_FALSE; } cal = new GregorianCalendar(Locale::createFromName(locale_str), status); if (U_FAILURE(status)) { intl_error_set(NULL, status, "datefmt_format_object: could not create GregorianCalendar", 0); RETVAL_FALSE; goto cleanup; } } else { intl_error_set(NULL, status, "datefmt_format_object: the passed object " "must be an instance of either IntlCalendar or DateTime", 0); RETURN_FALSE; } if (pattern) { df = new SimpleDateFormat( UnicodeString(Z_STRVAL_P(format), Z_STRLEN_P(format), UnicodeString::kInvariant), Locale::createFromName(locale_str), status); if (U_FAILURE(status)) { intl_error_set(NULL, status, "datefmt_format_object: could not create SimpleDateFormat", 0); RETVAL_FALSE; goto cleanup; } } else { df = DateFormat::createDateTimeInstance(dateStyle, timeStyle, Locale::createFromName(locale_str)); if (df == NULL) { /* according to ICU sources, this should never happen */ intl_error_set(NULL, status, "datefmt_format_object: could not create DateFormat", 0); RETVAL_FALSE; goto cleanup; } } //must be in this order (or have the cal adopt the tz) df->adoptCalendar(cal); cal = NULL; df->adoptTimeZone(timeZone); timeZone = NULL; { char *ret_str; int ret_str_len; UnicodeString result = UnicodeString(); df->format(date, result); if (intl_charFromString(result, &ret_str, &ret_str_len, &status) == FAILURE) { intl_error_set(NULL, status, "datefmt_format_object: error converting result to UTF-8", 0); RETVAL_FALSE; goto cleanup; } RETVAL_STRINGL(ret_str, ret_str_len); //??? efree(ret_str); } cleanup: delete df; delete timeZone; delete cal; }
U_CFUNC PHP_FUNCTION(intlcal_from_date_time) { zval **zv_arg, *zv_datetime = NULL; double millis; php_date_obj *datetime; char *locale_str = NULL; int locale_str_len; TimeZone *timeZone; UErrorCode status = U_ZERO_ERROR; Calendar *cal; intl_error_reset(NULL TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|s!", &zv_arg, &locale_str, &locale_str_len) == FAILURE) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intlcal_from_date_time: bad arguments", 0 TSRMLS_CC); RETURN_NULL(); } if (!(Z_TYPE_PP(zv_arg) == IS_OBJECT && instanceof_function( Z_OBJCE_PP(zv_arg), php_date_get_date_ce() TSRMLS_CC))) { ALLOC_INIT_ZVAL(zv_datetime); object_init_ex(zv_datetime, php_date_get_date_ce()); zend_call_method_with_1_params(&zv_datetime, NULL, NULL, "__construct", NULL, *zv_arg); if (EG(exception)) { zend_object_store_ctor_failed(zv_datetime TSRMLS_CC); goto error; } } else { zv_datetime = *zv_arg; } datetime = (php_date_obj*)zend_object_store_get_object(zv_datetime TSRMLS_CC); if (!datetime->time) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intlcal_from_date_time: DateTime object is unconstructed", 0 TSRMLS_CC); goto error; } if (intl_datetime_decompose(zv_datetime, &millis, NULL, NULL, "intlcal_from_date_time" TSRMLS_CC) == FAILURE) { goto error; } if (!datetime->time->is_localtime) { timeZone = TimeZone::getGMT()->clone(); } else { timeZone = timezone_convert_datetimezone(datetime->time->zone_type, datetime, 1, NULL, "intlcal_from_date_time" TSRMLS_CC); if (timeZone == NULL) { goto error; } } if (!locale_str) { locale_str = const_cast<char*>(intl_locale_get_default(TSRMLS_C)); } cal = Calendar::createInstance(timeZone, Locale::createFromName(locale_str), status); if (cal == NULL) { delete timeZone; intl_error_set(NULL, status, "intlcal_from_date_time: " "error creating ICU Calendar object", 0 TSRMLS_CC); goto error; } cal->setTime(millis, status); if (U_FAILURE(status)) { /* time zone was adopted by cal; should not be deleted here */ delete cal; intl_error_set(NULL, status, "intlcal_from_date_time: " "error creating ICU Calendar::setTime()", 0 TSRMLS_CC); goto error; } calendar_object_create(return_value, cal TSRMLS_CC); error: if (zv_datetime != *zv_arg) { zval_ptr_dtor(&zv_datetime); } }