From 3a81f90ebc51140484c617539b1a5fb0e117f4e2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Thu, 17 May 2012 23:18:51 +0200 Subject: [PATCH] Added IntlCalendar::toDateTime() --- ext/intl/calendar/calendar_class.cpp | 1 + ext/intl/calendar/calendar_methods.cpp | 80 +++++++++++++++++++ ext/intl/calendar/calendar_methods.h | 2 + ext/intl/php_intl.c | 1 + ext/intl/tests/badargs.phpt | 5 +- ext/intl/tests/calendar_toDateTime_basic.phpt | 23 ++++++ ext/intl/tests/calendar_toDateTime_error.phpt | 41 ++++++++++ 7 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 ext/intl/tests/calendar_toDateTime_basic.phpt create mode 100644 ext/intl/tests/calendar_toDateTime_error.phpt diff --git a/ext/intl/calendar/calendar_class.cpp b/ext/intl/calendar/calendar_class.cpp index 9f5db6f29c..43cbc4af85 100644 --- a/ext/intl/calendar/calendar_class.cpp +++ b/ext/intl/calendar/calendar_class.cpp @@ -431,6 +431,7 @@ static const zend_function_entry Calendar_class_functions[] = { PHP_ME_MAPPING(setSkippedWallTimeOption,intlcal_set_skipped_wall_time_option,ainfo_cal_wall_time_option,ZEND_ACC_PUBLIC) #endif PHP_ME_MAPPING(fromDateTime, intlcal_from_date_time, ainfo_cal_from_date_time, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC) + PHP_ME_MAPPING(toDateTime, intlcal_to_date_time, ainfo_cal_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getErrorCode, intlcal_get_error_code, ainfo_cal_void, ZEND_ACC_PUBLIC) PHP_ME_MAPPING(getErrorMessage, intlcal_get_error_message, ainfo_cal_void, ZEND_ACC_PUBLIC) PHP_FE_END diff --git a/ext/intl/calendar/calendar_methods.cpp b/ext/intl/calendar/calendar_methods.cpp index 82ccd80d0b..fc0a3064d2 100644 --- a/ext/intl/calendar/calendar_methods.cpp +++ b/ext/intl/calendar/calendar_methods.cpp @@ -1200,6 +1200,86 @@ error: } } +U_CFUNC PHP_FUNCTION(intlcal_to_date_time) +{ + zval *retval = NULL; + CALENDAR_METHOD_INIT_VARS; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", + &object, Calendar_ce_ptr) == FAILURE) { + intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, + "intlcal_to_date_time: bad arguments", 0 TSRMLS_CC); + RETURN_FALSE; + } + + CALENDAR_METHOD_FETCH_OBJECT; + + /* There are no exported functions in ext/date to this + * in a more native fashion */ + double date = co->ucal->getTime(CALENDAR_ERROR_CODE(co)) / 1000.; + int64_t ts; + char ts_str[sizeof("@-9223372036854775808")]; + int ts_str_len; + zval ts_zval = zval_used_for_init; + + INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed"); + + if (date > (double)U_INT64_MAX || date < (double)U_INT64_MIN) { + intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR, + "intlcal_to_date_time: The calendar date is out of the " + "range for a 64-bit integer", 0 TSRMLS_CC); + RETURN_FALSE; + } + + ts = (int64_t)date; + + ts_str_len = slprintf(ts_str, sizeof(ts_str), "@%I64d", ts); + ZVAL_STRINGL(&ts_zval, ts_str, ts_str_len, 0); + + /* Now get the time zone */ + const TimeZone& tz = co->ucal->getTimeZone(); + zval *timezone_zval = timezone_convert_to_datetimezone( + &tz, CALENDAR_ERROR_P(co), "intlcal_to_date_time" TSRMLS_CC); + if (timezone_zval == NULL) { + RETURN_FALSE; + } + + /* resources allocated from now on */ + + /* Finally, instantiate object and call constructor */ + object_init_ex(return_value, php_date_get_date_ce()); + zend_call_method_with_2_params(&return_value, NULL, NULL, "__construct", + NULL, &ts_zval, timezone_zval); + if (EG(exception)) { + intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR, + "intlcal_to_date_time: DateTime constructor has thrown exception", + 1 TSRMLS_CC); + zend_object_store_ctor_failed(return_value TSRMLS_CC); + zval_ptr_dtor(&return_value); + + RETVAL_FALSE; + goto error; + } + + /* due to bug #40743, we have to set the time zone again */ + zend_call_method_with_1_params(&return_value, NULL, NULL, "settimezone", + &retval, timezone_zval); + if (retval == NULL || Z_TYPE_P(retval) == IS_BOOL) { + intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR, + "intlcal_to_date_time: call to DateTime::setTimeZone has failed", + 1 TSRMLS_CC); + zval_ptr_dtor(&return_value); + RETVAL_FALSE; + goto error; + } + +error: + zval_ptr_dtor(&timezone_zval); + if (retval != NULL) { + zval_ptr_dtor(&retval); + } +} + U_CFUNC PHP_FUNCTION(intlcal_get_error_code) { CALENDAR_METHOD_INIT_VARS; diff --git a/ext/intl/calendar/calendar_methods.h b/ext/intl/calendar/calendar_methods.h index e0055711ae..2be13e4920 100644 --- a/ext/intl/calendar/calendar_methods.h +++ b/ext/intl/calendar/calendar_methods.h @@ -103,6 +103,8 @@ PHP_FUNCTION(intlcal_set_skipped_wall_time_option); PHP_FUNCTION(intlcal_from_date_time); +PHP_FUNCTION(intlcal_to_date_time); + PHP_FUNCTION(intlcal_get_error_code); PHP_FUNCTION(intlcal_get_error_message); diff --git a/ext/intl/php_intl.c b/ext/intl/php_intl.c index 4924fdef39..db8e00392c 100755 --- a/ext/intl/php_intl.c +++ b/ext/intl/php_intl.c @@ -796,6 +796,7 @@ zend_function_entry intl_functions[] = { PHP_FE( intlcal_set_lenient, ainfo_cal_set_lenient ) PHP_FE( intlcal_equals, ainfo_cal_other_cal ) PHP_FE( intlcal_from_date_time, ainfo_cal_from_date_time ) + PHP_FE( intlcal_to_date_time, ainfo_cal_only_cal ) #if U_ICU_VERSION_MAJOR_NUM >= 49 PHP_FE( intlcal_get_repeated_wall_time_option, ainfo_cal_only_cal ) PHP_FE( intlcal_get_skipped_wall_time_option, ainfo_cal_only_cal ) diff --git a/ext/intl/tests/badargs.phpt b/ext/intl/tests/badargs.phpt index 9232bbf0c1..b8f48b371e 100755 --- a/ext/intl/tests/badargs.phpt +++ b/ext/intl/tests/badargs.phpt @@ -13,7 +13,10 @@ foreach($funcs as $func) { if($rfunc->getNumberOfRequiredParameters() == 0) { continue; } - $res = $func($arg); + + try { + $res = $func($arg); + } catch (Exception $e) { continue; } if($res != false) { echo "$func: "; var_dump($res); diff --git a/ext/intl/tests/calendar_toDateTime_basic.phpt b/ext/intl/tests/calendar_toDateTime_basic.phpt new file mode 100644 index 0000000000..d38487dabf --- /dev/null +++ b/ext/intl/tests/calendar_toDateTime_basic.phpt @@ -0,0 +1,23 @@ +--TEST-- +IntlCalendar::toDateTime(): basic test +--SKIPIF-- +toDateTime(); + +var_dump($dt->format("c"), $dt->getTimeZone()->getName()); +?> +==DONE== +--EXPECT-- +string(25) "2012-05-17T17:35:36+01:00" +string(13) "Europe/Lisbon" +==DONE== \ No newline at end of file diff --git a/ext/intl/tests/calendar_toDateTime_error.phpt b/ext/intl/tests/calendar_toDateTime_error.phpt new file mode 100644 index 0000000000..961a9c86a6 --- /dev/null +++ b/ext/intl/tests/calendar_toDateTime_error.phpt @@ -0,0 +1,41 @@ +--TEST-- +IntlCalendar::toDateTime(): bad arguments +--SKIPIF-- +toDateTime(3)); + +var_dump(intlcal_to_date_time($cal, 3)); + +$cal = new IntlGregorianCalendar("Etc/Unknown"); +try { +var_dump($cal->toDateTime()); +} catch (Exception $e) { +var_dump("exception: {$e->getMessage()}"); +} + +var_dump(intlcal_to_date_time(3)); + +--EXPECTF-- + +Warning: IntlCalendar::toDateTime() expects exactly 0 parameters, 1 given in %s on line %d + +Warning: IntlCalendar::toDateTime(): intlcal_to_date_time: bad arguments in %s on line %d +bool(false) + +Warning: intlcal_to_date_time() expects exactly 1 parameter, 2 given in %s on line %d + +Warning: intlcal_to_date_time(): intlcal_to_date_time: bad arguments in %s on line %d +bool(false) + +Warning: IntlCalendar::toDateTime(): intlcal_to_date_time: DateTimeZone constructor threw exception in %s on line %d +string(77) "exception: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)" + +Catchable fatal error: Argument 1 passed to intlcal_to_date_time() must be an instance of IntlCalendar, integer given in %s on line %d -- 2.40.0