#include <unicode/locid.h>
#include <unicode/calendar.h>
#include <unicode/ustring.h>
+
#include "../intl_convertcpp.h"
+#include "../common/common_date.h"
+
extern "C" {
#define USE_TIMEZONE_POINTER 1
#include "../timezone/timezone_class.h"
#include <ext/date/php_date.h>
}
-U_CFUNC double intl_zval_to_millis(zval *z, UErrorCode *status TSRMLS_DC)
+#ifndef INFINITY
+#define INFINITY (DBL_MAX+DBL_MAX)
+#endif
+
+#ifndef NAN
+#define NAN (INFINITY-INFINITY)
+#endif
+
+/* {{{ timezone_convert_datetimezone
+ * The timezone in DateTime and DateTimeZone is not unified. */
+U_CFUNC TimeZone *timezone_convert_datetimezone(int type,
+ void *object,
+ int is_datetime,
+ intl_error *outside_error,
+ const char *func TSRMLS_DC)
{
- double rv = NAN;
- long lv;
- int type;
+ char *id = NULL,
+ offset_id[] = "GMT+00:00";
+ int id_len = 0;
+ char *message;
+ TimeZone *timeZone;
+
+ switch (type) {
+ case TIMELIB_ZONETYPE_ID:
+ id = is_datetime
+ ? ((php_date_obj*)object)->time->tz_info->name
+ : ((php_timezone_obj*)object)->tzi.tz->name;
+ id_len = strlen(id);
+ break;
+ case TIMELIB_ZONETYPE_OFFSET: {
+ int offset_mins = is_datetime
+ ? -((php_date_obj*)object)->time->z
+ : -(int)((php_timezone_obj*)object)->tzi.utc_offset,
+ hours = offset_mins / 60,
+ minutes = offset_mins - hours * 60;
+ minutes *= minutes > 0 ? 1 : -1;
+
+ if (offset_mins <= -24 * 60 || offset_mins >= 24 * 60) {
+ spprintf(&message, 0, "%s: object has an time zone offset "
+ "that's too large", func);
+ intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR,
+ message, 1 TSRMLS_CC);
+ efree(message);
+ return NULL;
+ }
- if (U_FAILURE(*status)) {
+ id = offset_id;
+ id_len = slprintf(id, sizeof(offset_id), "GMT%+03d:%02d",
+ hours, minutes);
+ break;
+ }
+ case TIMELIB_ZONETYPE_ABBR:
+ id = is_datetime
+ ? ((php_date_obj*)object)->time->tz_abbr
+ : ((php_timezone_obj*)object)->tzi.z.abbr;
+ id_len = strlen(id);
+ break;
+ }
+
+ UnicodeString s = UnicodeString(id, id_len, US_INV);
+ timeZone = TimeZone::createTimeZone(s);
+#if U_ICU_VERSION_MAJOR_NUM >= 49
+ if (*timeZone == TimeZone::getUnknown()) {
+#else
+ UnicodeString resultingId;
+ timeZone->getID(resultingId);
+ if (resultingId == UnicodeString("Etc/Unknown", -1, US_INV)
+ || resultingId == UnicodeString("GMT", -1, US_INV)) {
+#endif
+ spprintf(&message, 0, "%s: time zone id '%s' "
+ "extracted from ext/date DateTimeZone not recognized", func, id);
+ intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR,
+ message, 1 TSRMLS_CC);
+ efree(message);
+ delete timeZone;
+ return NULL;
+ }
+ return timeZone;
+}
+/* }}} */
+
+U_CFUNC int intl_datetime_decompose(zval *z, double *millis, TimeZone **tz,
+ intl_error *err, const char *func TSRMLS_DC)
+{
+ zval retval;
+ zval *zfuncname;
+ char *message;
+
+ if (err && U_FAILURE(err->code)) {
+ return FAILURE;
+ }
+
+ if (millis) {
+ *millis = NAN;
+ }
+ if (tz) {
+ *tz = NULL;
+ }
+
+ if (millis) {
+ INIT_ZVAL(retval);
+ MAKE_STD_ZVAL(zfuncname);
+ ZVAL_STRING(zfuncname, "getTimestamp", 1);
+ if (call_user_function(NULL, &(z), zfuncname, &retval, 0, NULL TSRMLS_CC)
+ != SUCCESS || Z_TYPE(retval) != IS_LONG) {
+ spprintf(&message, 0, "%s: error calling ::getTimeStamp() on the "
+ "object", func);
+ intl_errors_set(err, U_INTERNAL_PROGRAM_ERROR,
+ message, 1 TSRMLS_CC);
+ efree(message);
+ zval_ptr_dtor(&zfuncname);
+ return FAILURE;
+ }
+
+ *millis = U_MILLIS_PER_SECOND * (double)Z_LVAL(retval);
+ zval_ptr_dtor(&zfuncname);
+ }
+
+ if (tz) {
+ php_date_obj *datetime;
+ datetime = (php_date_obj*)zend_object_store_get_object(z TSRMLS_CC);
+ if (!datetime->time) {
+ spprintf(&message, 0, "%s: the DateTime object is not properly "
+ "initialized", func);
+ intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR,
+ message, 1 TSRMLS_CC);
+ efree(message);
+ return FAILURE;
+ }
+ if (!datetime->time->is_localtime) {
+ *tz = TimeZone::getGMT()->clone();
+ } else {
+ *tz = timezone_convert_datetimezone(datetime->time->zone_type,
+ datetime, 1, NULL, func TSRMLS_CC);
+ if (*tz == NULL) {
+ spprintf(&message, 0, "%s: could not convert DateTime's "
+ "time zone", func);
+ intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR,
+ message, 1 TSRMLS_CC);
+ efree(message);
+ return FAILURE;
+ }
+ }
+ }
+
+ return SUCCESS;
+}
+
+U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func TSRMLS_DC)
+{
+ double rv = NAN;
+ long lv;
+ int type;
+ char *message;
+
+ if (err && U_FAILURE(err->code)) {
return NAN;
}
} else if (type == IS_LONG) {
rv = U_MILLIS_PER_SECOND * (double)lv;
} else {
- *status = U_ILLEGAL_ARGUMENT_ERROR;
+ spprintf(&message, 0, "%s: string '%s' is not numeric, "
+ "which would be required for it to be a valid date", func,
+ Z_STRVAL_P(z));
+ intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR,
+ message, 1 TSRMLS_CC);
+ efree(message);
}
break;
case IS_LONG:
break;
case IS_OBJECT:
if (instanceof_function(Z_OBJCE_P(z), php_date_get_date_ce() TSRMLS_CC)) {
- zval retval;
- zval *zfuncname;
- INIT_ZVAL(retval);
- MAKE_STD_ZVAL(zfuncname);
- ZVAL_STRING(zfuncname, "getTimestamp", 1);
- if (call_user_function(NULL, &(z), zfuncname, &retval, 0, NULL TSRMLS_CC)
- != SUCCESS || Z_TYPE(retval) != IS_LONG) {
- *status = U_INTERNAL_PROGRAM_ERROR;
- } else {
- rv = U_MILLIS_PER_SECOND * (double)Z_LVAL(retval);
- }
- zval_ptr_dtor(&zfuncname);
+ intl_datetime_decompose(z, &rv, NULL, err, func TSRMLS_CC);
} else if (instanceof_function(Z_OBJCE_P(z), Calendar_ce_ptr TSRMLS_CC)) {
Calendar_object *co = (Calendar_object *)
zend_object_store_get_object(z TSRMLS_CC );
if (co->ucal == NULL) {
- *status = U_ILLEGAL_ARGUMENT_ERROR;
+ spprintf(&message, 0, "%s: IntlCalendar object is not properly "
+ "constructed", func);
+ intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR,
+ message, 1 TSRMLS_CC);
+ efree(message);
} else {
- rv = (double)co->ucal->getTime(*status);
+ UErrorCode status = UErrorCode();
+ rv = (double)co->ucal->getTime(status);
+ if (U_FAILURE(status)) {
+ spprintf(&message, 0, "%s: call to internal "
+ "Calendar::getTime() has failed", func);
+ intl_errors_set(err, status, message, 1 TSRMLS_CC);
+ efree(message);
+ }
}
} else {
/* TODO: try with cast(), get() to obtain a number */
- *status = U_ILLEGAL_ARGUMENT_ERROR;
+ spprintf(&message, 0, "%s: invalid object type for date/time "
+ "(only IntlCalendar and DateTime permitted)", func);
+ intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR,
+ message, 1 TSRMLS_CC);
+ efree(message);
}
break;
default:
- *status = U_ILLEGAL_ARGUMENT_ERROR;
+ spprintf(&message, 0, "%s: invalid PHP type for date", func);
+ intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR,
+ message, 1 TSRMLS_CC);
+ efree(message);
+ break;
}
return rv;
U_CDECL_BEGIN
#include <php.h>
+#include "../intl_error.h"
U_CDECL_END
-U_CFUNC double intl_zval_to_millis(zval *z, UErrorCode *status TSRMLS_DC);
+#ifdef __cplusplus
+
+#include <unicode/timezone.h>
+
+U_CFUNC TimeZone *timezone_convert_datetimezone(int type, void *object, int is_datetime, intl_error *outside_error, const char *func TSRMLS_DC);
+U_CFUNC int intl_datetime_decompose(zval *z, double *millis, TimeZone **tz,
+ intl_error *err, const char *func TSRMLS_DC);
+
+#endif
+
+U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func TSRMLS_DC);
#endif /* COMMON_DATE_H */
dateformat/dateformat_attr.c \
dateformat/dateformat_data.c \
dateformat/dateformat_format.c \
+ dateformat/dateformat_format_object.cpp \
dateformat/dateformat_parse.c \
dateformat/dateformat_create.cpp \
dateformat/dateformat_attrcpp.cpp \
dateformat_class.c \
dateformat_attr.c \
dateformat_format.c \
+ dateformat_format_object.cpp \
dateformat_parse.c \
dateformat_data.c \
dateformat_attrcpp.cpp \
#include "php_intl.h"
#include "dateformat_data.h"
#include "dateformat_format.h"
+#include "dateformat_format_object.h"
#include "dateformat_parse.h"
#include "dateformat.h"
#include "dateformat_attr.h"
ZEND_ARG_INFO(0, array)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_intldateformatter_format_object, 0, 0, 1)
+ ZEND_ARG_INFO(0, object)
+ ZEND_ARG_INFO(0, format)
+ ZEND_ARG_INFO(0, locale)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO(arginfo_intldateformatter_getdatetype, 0)
ZEND_END_ARG_INFO()
PHP_NAMED_FE( setLenient, ZEND_FN( datefmt_set_lenient ), arginfo_intldateformatter_setlenient )
PHP_NAMED_FE( isLenient, ZEND_FN( datefmt_is_lenient ), arginfo_intldateformatter_getdatetype )
PHP_NAMED_FE( format, ZEND_FN( datefmt_format ), arginfo_intldateformatter_format )
+ PHP_ME_MAPPING( formatObject, datefmt_format_object, arginfo_intldateformatter_format_object, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_NAMED_FE( parse, ZEND_FN( datefmt_parse), datefmt_parse_args )
PHP_NAMED_FE( localtime, ZEND_FN( datefmt_localtime ), datefmt_parse_args )
PHP_NAMED_FE( getErrorCode, ZEND_FN( datefmt_get_error_code ), arginfo_intldateformatter_getdatetype )
timestamp = internal_get_timestamp(dfo, hash_arr TSRMLS_CC);
INTL_METHOD_CHECK_STATUS(dfo, "datefmt_format: date formatting failed")
} else {
- timestamp = intl_zval_to_millis(zarg,
- &INTL_DATA_ERROR_CODE(dfo) TSRMLS_CC);
- INTL_METHOD_CHECK_STATUS(dfo, "datefmt_format: could not convert input "
- "into a date")
+ timestamp = intl_zval_to_millis(zarg, INTL_DATA_ERROR_P(dfo),
+ "datefmt_format" TSRMLS_CC);
+ if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
+ RETURN_FALSE;
+ }
}
internal_format( dfo, timestamp, return_value TSRMLS_CC);
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Gustavo Lopes <cataphract@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#include "../intl_cppshims.h"
+
+#include <unicode/calendar.h>
+#include <unicode/gregocal.h>
+#include <unicode/datefmt.h>
+#include <unicode/smpdtfmt.h>
+#include <unicode/locid.h>
+
+#include "../intl_convertcpp.h"
+
+extern "C" {
+#include "../php_intl.h"
+#include "../locale/locale.h"
+#define USE_CALENDAR_POINTER 1
+#include "../calendar/calendar_class.h"
+#include <ext/date/php_date.h>
+#include "../common/common_date.h"
+}
+
+static const DateFormat::EStyle valid_styles[] = {
+ DateFormat::kNone,
+ DateFormat::kFull,
+ DateFormat::kLong,
+ DateFormat::kMedium,
+ DateFormat::kShort,
+ DateFormat::kFullRelative,
+ DateFormat::kLongRelative,
+ DateFormat::kMediumRelative,
+ DateFormat::kShortRelative,
+};
+
+static bool valid_format(zval **z) {
+ if (Z_TYPE_PP(z) == IS_LONG) {
+ long lval = Z_LVAL_PP(z);
+ for (int i = 0; i < sizeof(valid_styles) / sizeof(*valid_styles); i++) {
+ if ((long)valid_styles[i] == lval) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+U_CFUNC PHP_FUNCTION(datefmt_format_object)
+{
+ zval *object,
+ **format = NULL;
+ const char *locale_str = NULL;
+ int 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() TSRMLS_CC, "o|Zs!",
+ &object, &format, &locale_str, &locale_len) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (!locale_str) {
+ locale_str = intl_locale_get_default(TSRMLS_C);
+ }
+
+ if (format == NULL || Z_TYPE_PP(format) == IS_NULL) {
+ //nothing
+ } else if (Z_TYPE_PP(format) == IS_ARRAY) {
+ HashTable *ht = Z_ARRVAL_PP(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 TSRMLS_CC);
+ RETURN_FALSE;
+ }
+
+ zend_hash_internal_pointer_reset_ex(ht, &pos);
+ zend_hash_get_current_data_ex(ht, (void**)&z, &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 TSRMLS_CC);
+ RETURN_FALSE;
+ }
+ dateStyle = (DateFormat::EStyle)Z_LVAL_PP(z);
+
+ zend_hash_move_forward_ex(ht, &pos);
+ zend_hash_get_current_data_ex(ht, (void**)&z, &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 TSRMLS_CC);
+ RETURN_FALSE;
+ }
+ timeStyle = (DateFormat::EStyle)Z_LVAL_PP(z);
+ } else if (Z_TYPE_PP(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 TSRMLS_CC);
+ RETURN_FALSE;
+ }
+ dateStyle = timeStyle = (DateFormat::EStyle)Z_LVAL_PP(format);
+ } else {
+ convert_to_string_ex(format);
+ if (Z_STRLEN_PP(format) == 0) {
+ intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "datefmt_format_object: the format is empty", 0 TSRMLS_CC);
+ 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 TSRMLS_CC)) {
+ Calendar *obj_cal = calendar_fetch_native_calendar(object TSRMLS_CC);
+ if (obj_cal == NULL) {
+ intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
+ "datefmt_format_object: bad IntlCalendar instance: "
+ "not initialized properly", 0 TSRMLS_CC);
+ 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 TSRMLS_CC);
+ RETVAL_FALSE;
+ goto cleanup;
+ }
+ cal = obj_cal->clone();
+ } else if (instanceof_function(instance_ce, php_date_get_date_ce() TSRMLS_CC)) {
+ if (intl_datetime_decompose(object, &date, &timeZone, NULL,
+ "datefmt_format_object" TSRMLS_CC) == 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 TSRMLS_CC);
+ 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 TSRMLS_CC);
+ RETURN_FALSE;
+ }
+
+ if (pattern) {
+ df = new SimpleDateFormat(
+ UnicodeString(Z_STRVAL_PP(format), Z_STRLEN_PP(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 TSRMLS_CC);
+ 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 TSRMLS_CC);
+ 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;
+
+ {
+ UnicodeString result = UnicodeString();
+ df->format(date, result);
+
+ Z_TYPE_P(return_value) = IS_STRING;
+ if (intl_charFromString(result, &Z_STRVAL_P(return_value),
+ &Z_STRLEN_P(return_value), &status) == FAILURE) {
+ intl_error_set(NULL, status,
+ "datefmt_format_object: error converting result to UTF-8",
+ 0 TSRMLS_CC);
+ RETVAL_FALSE;
+ goto cleanup;
+ }
+ }
+
+
+cleanup:
+ delete df;
+ delete timeZone;
+ delete cal;
+}
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Gustavo Lopes <cataphract@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include <php.h>
+
+PHP_FUNCTION(datefmt_format_object);
#include "../timezone/timezone_class.h"
}
-#ifndef INFINITY
-#define INFINITY (DBL_MAX+DBL_MAX)
-#endif
-
-#ifndef NAN
-#define NAN (INFINITY-INFINITY)
-#endif
-
#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 48
#define HAS_MESSAGE_PATTERN 1
#endif
}
case Formattable::kDate:
{
- double dd = intl_zval_to_millis(*elem, &err.code TSRMLS_CC);
+ double dd = intl_zval_to_millis(*elem, &err, "msgfmt_format" TSRMLS_CC);
if (U_FAILURE(err.code)) {
char *message, *key_char;
int key_len;
#include "dateformat/dateformat_attr.h"
#include "dateformat/dateformat_attrcpp.h"
#include "dateformat/dateformat_format.h"
+#include "dateformat/dateformat_format_object.h"
#include "dateformat/dateformat_parse.h"
#include "dateformat/dateformat_data.h"
ZEND_ARG_INFO(0, array)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_datefmt_format_object, 0, 0, 1)
+ ZEND_ARG_INFO(0, object)
+ ZEND_ARG_INFO(0, format)
+ ZEND_ARG_INFO(0, locale)
+ZEND_END_ARG_INFO()
+
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_datefmt_create, 0, 0, 3)
ZEND_ARG_INFO(0, locale)
ZEND_ARG_INFO(0, date_type)
PHP_FE( datefmt_is_lenient, arginfo_msgfmt_get_locale )
PHP_FE( datefmt_set_lenient, arginfo_msgfmt_get_locale )
PHP_FE( datefmt_format, arginfo_datefmt_format )
+ PHP_FE( datefmt_format_object, arginfo_datefmt_format_object )
PHP_FE( datefmt_parse, datefmt_parse_args )
PHP_FE( datefmt_localtime , datefmt_parse_args )
PHP_FE( datefmt_get_error_code, arginfo_msgfmt_get_error_code )
Date is: stdClass::__set_state(array(
))
------------
-Error while formatting as: 'datefmt_format: could not convert input into a date: U_ILLEGAL_ARGUMENT_ERROR'
+Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTime permitted): U_ILLEGAL_ARGUMENT_ERROR'
------------
Date is: stdClass::__set_state(array(
))
------------
-Error while formatting as: 'datefmt_format: could not convert input into a date: U_ILLEGAL_ARGUMENT_ERROR'
+Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTime permitted): U_ILLEGAL_ARGUMENT_ERROR'
------------
Date is: stdClass::__set_state(array(
))
------------
-Error while formatting as: 'datefmt_format: could not convert input into a date: U_ILLEGAL_ARGUMENT_ERROR'
+Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTime permitted): U_ILLEGAL_ARGUMENT_ERROR'
------------
Date is: stdClass::__set_state(array(
))
------------
-Error while formatting as: 'datefmt_format: could not convert input into a date: U_ILLEGAL_ARGUMENT_ERROR'
+Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTime permitted): U_ILLEGAL_ARGUMENT_ERROR'
------------
Date is: stdClass::__set_state(array(
))
------------
-Error while formatting as: 'datefmt_format: could not convert input into a date: U_ILLEGAL_ARGUMENT_ERROR'
+Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTime permitted): U_ILLEGAL_ARGUMENT_ERROR'
--- /dev/null
+--TEST--\r
+IntlDateFormatter::formatObject(): IntlCalendar tests\r
+--SKIPIF--\r
+<?php\r
+if (!extension_loaded('intl'))\r
+ die('skip intl extension not enabled');\r
+--FILE--\r
+<?php
+ini_set("intl.error_level", E_WARNING);
+ini_set("intl.default_locale", "pt_PT");
+ini_set("date.timezone", "Europe/Lisbon");
+
+$cal = IntlCalendar::fromDateTime('2012-01-01 00:00:00'); //Europe/Lisbon
+echo IntlDateFormatter::formatObject($cal), "\n";
+echo IntlDateFormatter::formatObject($cal, IntlDateFormatter::FULL), "\n";
+echo IntlDateFormatter::formatObject($cal, null, "en-US"), "\n";
+echo IntlDateFormatter::formatObject($cal, array(IntlDateFormatter::SHORT, IntlDateFormatter::FULL), "en-US"), "\n";
+echo IntlDateFormatter::formatObject($cal, 'E y-MM-d HH,mm,ss.SSS v', "en-US"), "\n";
+
+$cal = IntlCalendar::fromDateTime('2012-01-01 05:00:00+03:00');
+echo datefmt_format_object($cal, IntlDateFormatter::FULL), "\n";
+
+$cal = IntlCalendar::createInstance(null,'en-US@calendar=islamic-civil');
+$cal->setTime(strtotime('2012-01-01 00:00:00')*1000.);
+echo IntlDateFormatter::formatObject($cal), "\n";
+echo IntlDateFormatter::formatObject($cal, IntlDateFormatter::FULL, "en-US"), "\n";
+
+?>
+==DONE==
+\r
+--EXPECT--\r
+01/01/2012 00:00:00
+Domingo, 1 de Janeiro de 2012 0:00:00 Hora Padrão da Europa Ocidental
+Jan 1, 2012 12:00:00 AM
+1/1/12 12:00:00 AM Western European Standard Time
+Sun 2012-01-1 00,00,00.000 Portugal Time (Lisbon)
+Domingo, 1 de Janeiro de 2012 5:00:00 GMT+03:00
+06/02/1433 00:00:00
+Sunday, Safar 6, 1433 12:00:00 AM Western European Standard Time
+==DONE==
+\r
--- /dev/null
+--TEST--\r
+IntlDateFormatter::formatObject(): DateTime tests\r
+--SKIPIF--\r
+<?php\r
+if (!extension_loaded('intl'))\r
+ die('skip intl extension not enabled');\r
+--FILE--\r
+<?php
+ini_set("intl.error_level", E_WARNING);
+ini_set("intl.default_locale", "pt_PT");
+ini_set("date.timezone", "Europe/Lisbon");
+
+$dt = new DateTime('2012-01-01 00:00:00'); //Europe/Lisbon
+echo IntlDateFormatter::formatObject($dt), "\n";
+echo IntlDateFormatter::formatObject($dt, IntlDateFormatter::FULL), "\n";
+echo IntlDateFormatter::formatObject($dt, null, "en-US"), "\n";
+echo IntlDateFormatter::formatObject($dt, array(IntlDateFormatter::SHORT, IntlDateFormatter::FULL), "en-US"), "\n";
+echo IntlDateFormatter::formatObject($dt, 'E y-MM-d HH,mm,ss.SSS v', "en-US"), "\n";
+
+$dt = new DateTime('2012-01-01 05:00:00+03:00');
+echo IntlDateFormatter::formatObject($dt, IntlDateFormatter::FULL), "\n";
+
+?>
+==DONE==
+\r
+--EXPECT--\r
+01/01/2012 00:00:00
+Domingo, 1 de Janeiro de 2012 0:00:00 Hora Padrão da Europa Ocidental
+Jan 1, 2012 12:00:00 AM
+1/1/12 12:00:00 AM Western European Standard Time
+Sun 2012-01-1 00,00,00.000 Portugal Time (Lisbon)
+Domingo, 1 de Janeiro de 2012 5:00:00 GMT+03:00
+==DONE==
+\r
--- /dev/null
+--TEST--\r
+IntlDateFormatter::formatObject(): error conditions\r
+--SKIPIF--\r
+<?php\r
+if (!extension_loaded('intl'))\r
+ die('skip intl extension not enabled');\r
+--FILE--\r
+<?php
+ini_set("intl.error_level", E_WARNING);
+ini_set("intl.default_locale", "pt_PT");
+ini_set("date.timezone", "Europe/Lisbon");
+
+var_dump(IntlDateFormatter::formatObject());
+var_dump(IntlDateFormatter::formatObject(1));
+var_dump(IntlDateFormatter::formatObject(new stdclass));
+
+class A extends IntlCalendar {function __construct(){}}
+var_dump(IntlDateFormatter::formatObject(new A));
+class B extends DateTime {function __construct(){}}
+var_dump(IntlDateFormatter::formatObject(new B));
+
+$cal = IntlCalendar::createInstance();
+var_dump(IntlDateFormatter::formatObject($cal, -2));
+var_dump(IntlDateFormatter::formatObject($cal, array()));
+var_dump(IntlDateFormatter::formatObject($cal, array(1,2,3)));
+var_dump(IntlDateFormatter::formatObject($cal, array(array(), 1)));
+var_dump(IntlDateFormatter::formatObject($cal, array(1, -2)));
+var_dump(IntlDateFormatter::formatObject($cal, ""));
+var_dump(IntlDateFormatter::formatObject($cal, "YYYY", array()));
+
+?>
+==DONE==
+\r
+--EXPECTF--\r
+
+Warning: IntlDateFormatter::formatObject() expects at least 1 parameter, 0 given in %s on line %d
+bool(false)
+
+Warning: IntlDateFormatter::formatObject() expects parameter 1 to be object, integer given in %s on line %d
+bool(false)
+
+Warning: IntlDateFormatter::formatObject(): datefmt_format_object: the passed object must be an instance of either IntlCalendar or DateTime in %s on line %d
+bool(false)
+
+Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad IntlCalendar instance: not initialized properly in %s on line %d
+bool(false)
+
+Warning: DateTime::getTimestamp(): The DateTime object has not been correctly initialized by its constructor in %s on line %d
+
+Warning: IntlDateFormatter::formatObject(): datefmt_format_object: error calling ::getTimeStamp() on the object in %s on line %d
+bool(false)
+
+Warning: IntlDateFormatter::formatObject(): datefmt_format_object: the date/time format type is invalid in %s on line %d
+bool(false)
+
+Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad format; if array, it must have two elements in %s on line %d
+bool(false)
+
+Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad format; if array, it must have two elements in %s on line %d
+bool(false)
+
+Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad format; the date format (first element of the array) is not valid in %s on line %d
+bool(false)
+
+Warning: IntlDateFormatter::formatObject(): datefmt_format_object: bad format; the time format (second element of the array) is not valid in %s on line %d
+bool(false)
+
+Warning: IntlDateFormatter::formatObject(): datefmt_format_object: the format is empty in %s on line %d
+bool(false)
+
+Warning: IntlDateFormatter::formatObject() expects parameter 3 to be string, array given in %s on line %d
+bool(false)
+==DONE==
+\r
var_dump($mf->format(array("foo" => new stdclass())));
--EXPECTF--
+Warning: MessageFormatter::format(): msgfmt_format: invalid object type for date/time (only IntlCalendar and DateTime permitted) in %s on line %d
Warning: MessageFormatter::format(): The argument for key 'foo' cannot be used as a date or time in %s on line %d
bool(false)
#include <unicode/calendar.h>
#include "../intl_convertcpp.h"
+#include "../common/common_date.h"
+
extern "C" {
#include "../intl_convert.h"
#define USE_TIMEZONE_POINTER 1
}
/* }}} */
-/* {{{ timezone_convert_datetimezone
- * The timezone in DateTime and DateTimeZone is not unified. */
-U_CFUNC TimeZone *timezone_convert_datetimezone(int type,
- void *object,
- int is_datetime,
- intl_error *outside_error,
- const char *func TSRMLS_DC)
-{
- char *id = NULL,
- offset_id[] = "GMT+00:00";
- int id_len = 0;
- char *message;
- TimeZone *timeZone;
-
- switch (type) {
- case TIMELIB_ZONETYPE_ID:
- id = is_datetime
- ? ((php_date_obj*)object)->time->tz_info->name
- : ((php_timezone_obj*)object)->tzi.tz->name;
- id_len = strlen(id);
- break;
- case TIMELIB_ZONETYPE_OFFSET: {
- int offset_mins = is_datetime
- ? -((php_date_obj*)object)->time->z
- : -(int)((php_timezone_obj*)object)->tzi.utc_offset,
- hours = offset_mins / 60,
- minutes = offset_mins - hours * 60;
- minutes *= minutes > 0 ? 1 : -1;
-
- if (offset_mins <= -24 * 60 || offset_mins >= 24 * 60) {
- spprintf(&message, 0, "%s: object has an time zone offset "
- "that's too large", func);
- intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR,
- message, 1 TSRMLS_CC);
- efree(message);
- return NULL;
- }
-
- id = offset_id;
- id_len = slprintf(id, sizeof(offset_id), "GMT%+03d:%02d",
- hours, minutes);
- break;
- }
- case TIMELIB_ZONETYPE_ABBR:
- id = is_datetime
- ? ((php_date_obj*)object)->time->tz_abbr
- : ((php_timezone_obj*)object)->tzi.z.abbr;
- id_len = strlen(id);
- break;
- }
-
- UnicodeString s = UnicodeString(id, id_len, US_INV);
- timeZone = TimeZone::createTimeZone(s);
-#if U_ICU_VERSION_MAJOR_NUM >= 49
- if (*timeZone == TimeZone::getUnknown()) {
-#else
- UnicodeString resultingId;
- timeZone->getID(resultingId);
- if (resultingId == UnicodeString("Etc/Unknown", -1, US_INV)
- || resultingId == UnicodeString("GMT", -1, US_INV)) {
-#endif
- spprintf(&message, 0, "%s: time zone id '%s' "
- "extracted from ext/date DateTimeZone not recognized", func, id);
- intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR,
- message, 1 TSRMLS_CC);
- efree(message);
- delete timeZone;
- return NULL;
- }
- return timeZone;
-}
-/* }}} */
-
/* {{{ timezone_convert_to_datetimezone
* Convert from TimeZone to DateTimeZone object */
U_CFUNC zval *timezone_convert_to_datetimezone(const TimeZone *timeZone,
RETURN_FALSE; \
}
-TimeZone *timezone_convert_datetimezone(int type, void *object, int is_datetime, intl_error *outside_error, const char *func TSRMLS_DC);
zval *timezone_convert_to_datetimezone(const TimeZone *timeZone, intl_error *outside_error, const char *func TSRMLS_DC);
TimeZone *timezone_process_timezone_argument(zval **zv_timezone, intl_error *error, const char *func TSRMLS_DC);
#include <unicode/timezone.h>
#include <unicode/ustring.h>
#include "intl_convertcpp.h"
+
+#include "../common/common_date.h"
+
extern "C" {
#define USE_TIMEZONE_POINTER 1
#include "timezone_class.h"