]> granicus.if.org Git - php/commitdiff
Added IntlCalendar::fromDateTime()
authorGustavo André dos Santos Lopes <cataphract@php.net>
Fri, 6 Apr 2012 19:52:43 +0000 (21:52 +0200)
committerGustavo André dos Santos Lopes <cataphract@php.net>
Thu, 17 May 2012 15:23:47 +0000 (17:23 +0200)
IntlCalendar::fromDateTime(DateTime|string $dateTime[, string $locale)
intlcal_from_date_time(...)

If a string is given as the first argument, the method will try to
instantiate a new DateTime object and use that instead.

ext/intl/calendar/calendar_class.cpp
ext/intl/calendar/calendar_methods.cpp
ext/intl/calendar/calendar_methods.h
ext/intl/php_intl.c
ext/intl/tests/calendar_fromDateTime_basic.phpt [new file with mode: 0644]
ext/intl/tests/calendar_fromDateTime_error.phpt [new file with mode: 0644]

index ea5339d836fdb54e4e3688b88cd51081504d2a7e..9f5db6f29cf970dc89e875dfafac5fb84d22ec42 100644 (file)
@@ -351,6 +351,10 @@ ZEND_BEGIN_ARG_INFO_EX(ainfo_cal_setLenient, 0, 0, 1)
        ZEND_ARG_INFO(0, isLenient)
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_INFO_EX(ainfo_cal_from_date_time, 0, 0, 1)
+       ZEND_ARG_INFO(0, dateTime)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO_EX(ainfo_cal_wall_time_option, 0, 0, 1)
        ZEND_ARG_INFO(0, wallTimeOption)
 ZEND_END_ARG_INFO()
@@ -426,6 +430,7 @@ static const zend_function_entry Calendar_class_functions[] = {
        PHP_ME_MAPPING(setRepeatedWallTimeOption,intlcal_set_repeated_wall_time_option,ainfo_cal_wall_time_option,ZEND_ACC_PUBLIC)
        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(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
index 0c6450fce7c057a483b03543a09dc53adc8ffd72..e9565fc1210f1b87ececf616ccb036d6f9e16427 100644 (file)
@@ -1108,6 +1108,97 @@ U_CFUNC PHP_FUNCTION(intlcal_set_skipped_wall_time_option)
 
 #endif
 
+U_CFUNC PHP_FUNCTION(intlcal_from_date_time)
+{
+       zval                    **zv_arg,
+                                       *zv_datetime            = NULL,
+                                       *zv_timestamp           = NULL;
+       php_date_obj    *datetime;
+       char                    *locale_str                     = NULL;
+       int                             locale_str_len;
+       TimeZone                *timeZone;
+       UErrorCode              status                          = U_ZERO_ERROR;
+       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) {
+               intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
+                       "intlcal_from_date_time: DateTime object is unconstructed",
+                       0 TSRMLS_CC);
+               goto error;
+       }
+
+       zend_call_method_with_0_params(&zv_datetime, php_date_get_date_ce(),
+               NULL, "gettimestamp", &zv_timestamp);
+       if (!zv_timestamp || Z_TYPE_P(zv_timestamp) != IS_LONG) {
+               intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
+                       "intlcal_from_date_time: bad DateTime; call to "
+                       "DateTime::getTimestamp() failed", 0 TSRMLS_CC);
+               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));
+       }
+
+       Calendar *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(((UDate)Z_LVAL_P(zv_timestamp)) * 1000., status);
+    if (U_FAILURE(status)) {
+               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);
+       }
+       if (zv_timestamp) {
+               zval_ptr_dtor(&zv_timestamp);
+       }
+}
+
 U_CFUNC PHP_FUNCTION(intlcal_get_error_code)
 {
        CALENDAR_METHOD_INIT_VARS;
index 95ff5375b52bc5802b8f5e6366b74a048927a1d5..e0055711ae813f9a1972559bfe35a729c0e983c4 100644 (file)
@@ -101,6 +101,8 @@ PHP_FUNCTION(intlcal_set_repeated_wall_time_option);
 
 PHP_FUNCTION(intlcal_set_skipped_wall_time_option);
 
+PHP_FUNCTION(intlcal_from_date_time);
+
 PHP_FUNCTION(intlcal_get_error_code);
 
 PHP_FUNCTION(intlcal_get_error_message);
index aca3590e0111b668391467a32bc748419317436a..51aece69d55462e0558116cbce724a3ec5a3497b 100755 (executable)
@@ -556,6 +556,10 @@ ZEND_BEGIN_ARG_INFO_EX( ainfo_cal_set_lenient, 0, 0, 2 )
        ZEND_ARG_INFO( 0, isLenient )
 ZEND_END_ARG_INFO()
 
+ZEND_BEGIN_ARG_INFO_EX(ainfo_cal_from_date_time, 0, 0, 1)
+       ZEND_ARG_INFO(0, dateTime)
+ZEND_END_ARG_INFO()
+
 ZEND_BEGIN_ARG_INFO_EX( ainfo_cal_wall_time_option, 0, 0, 2 )
        ZEND_ARG_OBJ_INFO( 0, calendar, IntlCalendar, 0 )
        ZEND_ARG_INFO( 0, wallTimeOption )
@@ -785,6 +789,7 @@ zend_function_entry intl_functions[] = {
        PHP_FE( intlcal_set_first_day_of_week, ainfo_cal_dow )
        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 )
 #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/calendar_fromDateTime_basic.phpt b/ext/intl/tests/calendar_fromDateTime_basic.phpt
new file mode 100644 (file)
index 0000000..1863b78
--- /dev/null
@@ -0,0 +1,52 @@
+--TEST--
+IntlCalendar::fromDateTime(): basic test
+--SKIPIF--
+<?php
+if (!extension_loaded('intl'))
+       die('skip intl extension not enabled');
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+ini_set("intl.default_locale", "nl_NL");
+date_default_timezone_set('Europe/Lisbon');
+
+$cal = IntlCalendar::fromDateTime('2012-01-01 00:00:00 Europe/Rome');
+var_dump(
+       $cal->getTime(),
+       strtotime('2012-01-01 00:00:00 Europe/Rome') * 1000.,
+       $cal->getTimeZone()->getID(),
+       $cal->getLocale(1)
+);
+echo "\n";
+
+$cal = IntlCalendar::fromDateTime(new DateTime('2012-01-01 00:00:00 PST'), "pt_PT");
+var_dump(
+       $cal->getTime(),
+       strtotime('2012-01-01 00:00:00 PST') * 1000.,
+       $cal->getTimeZone()->getID(),
+       $cal->getLocale(1)
+);
+
+echo "\n";
+
+$cal = intlcal_from_date_time(new DateTime('2012-01-01 00:00:00 +03:40'));
+var_dump(
+       $cal->getTime(),
+       strtotime('2012-01-01 00:00:00 +03:40') * 1000.,
+       $cal->getTimeZone()->getID()
+);
+
+--EXPECTF--
+float(1325372400000)
+float(1325372400000)
+string(11) "Europe/Rome"
+string(5) "nl_NL"
+
+float(1325404800000)
+float(1325404800000)
+string(3) "PST"
+string(5) "pt_PT"
+
+float(1325362800000)
+float(1325362800000)
+string(%d) "GMT+03%S40"
diff --git a/ext/intl/tests/calendar_fromDateTime_error.phpt b/ext/intl/tests/calendar_fromDateTime_error.phpt
new file mode 100644 (file)
index 0000000..b3cb22a
--- /dev/null
@@ -0,0 +1,61 @@
+--TEST--
+IntlCalendar::fromDateTime(): errors
+--SKIPIF--
+<?php
+if (!extension_loaded('intl'))
+       die('skip intl extension not enabled');
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+ini_set("intl.default_locale", "nl");
+date_default_timezone_set('Europe/Lisbon');
+
+var_dump(IntlCalendar::fromDateTime());
+var_dump(IntlCalendar::fromDateTime(0,1,2));
+
+try {
+IntlCalendar::fromDateTime("foobar");
+} catch (Exception $e) {
+       echo "threw exception, OK";
+}
+class A extends DateTime {
+function __construct() {}
+}
+
+var_dump(IntlCalendar::fromDateTime(new A));
+
+$date = new DateTime('2012-01-01 00:00:00 +24:00');
+var_dump(IntlCalendar::fromDateTime($date));
+
+$date = new DateTime('2012-01-01 00:00:00 WEST');
+var_dump(IntlCalendar::fromDateTime($date));
+
+var_dump(intlcal_from_date_time());
+
+--EXPECTF--
+
+Warning: IntlCalendar::fromDateTime() expects at least 1 parameter, 0 given in %s on line %d
+
+Warning: IntlCalendar::fromDateTime(): intlcal_from_date_time: bad arguments in %s on line %d
+NULL
+
+Warning: IntlCalendar::fromDateTime() expects at most 2 parameters, 3 given in %s on line %d
+
+Warning: IntlCalendar::fromDateTime(): intlcal_from_date_time: bad arguments in %s on line %d
+NULL
+threw exception, OK
+Warning: DateTime::getTimestamp(): The DateTime object has not been correctly initialized by its constructor in %s on line %d
+
+Warning: IntlCalendar::fromDateTime(): intlcal_from_date_time: bad DateTime; call to DateTime::getTimestamp() failed in %s on line %d
+NULL
+
+Warning: IntlCalendar::fromDateTime(): intlcal_from_date_time: object has an time zone offset that's too large in %s on line %d
+NULL
+
+Warning: IntlCalendar::fromDateTime(): intlcal_from_date_time: time zone id 'WEST' extracted from ext/date DateTimeZone not recognized in %s on line %d
+NULL
+
+Warning: intlcal_from_date_time() expects at least 1 parameter, 0 given in %s on line %d
+
+Warning: intlcal_from_date_time(): intlcal_from_date_time: bad arguments in %s on line %d
+NULL