mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Merge branch 'datefmt_tz_cal_interop'
* datefmt_tz_cal_interop: Readded accidentally removed line Added IntlDateFormatter::formatObject(). Refactor Refactored internal_get_timestamp() Unified zval -> UDate conversions
This commit is contained in:
commit
99e48d3a57
19 changed files with 810 additions and 245 deletions
|
@ -23,7 +23,10 @@
|
||||||
#include <unicode/locid.h>
|
#include <unicode/locid.h>
|
||||||
#include <unicode/calendar.h>
|
#include <unicode/calendar.h>
|
||||||
#include <unicode/ustring.h>
|
#include <unicode/ustring.h>
|
||||||
|
|
||||||
#include "../intl_convertcpp.h"
|
#include "../intl_convertcpp.h"
|
||||||
|
#include "../common/common_date.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "../php_intl.h"
|
#include "../php_intl.h"
|
||||||
#define USE_TIMEZONE_POINTER 1
|
#define USE_TIMEZONE_POINTER 1
|
||||||
|
|
250
ext/intl/common/common_date.cpp
Normal file
250
ext/intl/common/common_date.cpp
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| 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>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "../php_intl.h"
|
||||||
|
#define USE_CALENDAR_POINTER 1
|
||||||
|
#include "../calendar/calendar_class.h"
|
||||||
|
#include <ext/date/php_date.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Z_TYPE_P(z)) {
|
||||||
|
case IS_STRING:
|
||||||
|
type = is_numeric_string(Z_STRVAL_P(z), Z_STRLEN_P(z), &lv, &rv, 0);
|
||||||
|
if (type == IS_DOUBLE) {
|
||||||
|
rv *= U_MILLIS_PER_SECOND;
|
||||||
|
} else if (type == IS_LONG) {
|
||||||
|
rv = U_MILLIS_PER_SECOND * (double)lv;
|
||||||
|
} else {
|
||||||
|
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:
|
||||||
|
rv = U_MILLIS_PER_SECOND * (double)Z_LVAL_P(z);
|
||||||
|
break;
|
||||||
|
case IS_DOUBLE:
|
||||||
|
rv = U_MILLIS_PER_SECOND * Z_DVAL_P(z);
|
||||||
|
break;
|
||||||
|
case IS_OBJECT:
|
||||||
|
if (instanceof_function(Z_OBJCE_P(z), php_date_get_date_ce() TSRMLS_CC)) {
|
||||||
|
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) {
|
||||||
|
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 {
|
||||||
|
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 */
|
||||||
|
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:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
40
ext/intl/common/common_date.h
Normal file
40
ext/intl/common/common_date.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| 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> |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMMON_DATE_H
|
||||||
|
#define COMMON_DATE_H
|
||||||
|
|
||||||
|
#include <unicode/umachine.h>
|
||||||
|
|
||||||
|
U_CDECL_BEGIN
|
||||||
|
#include <php.h>
|
||||||
|
#include "../intl_error.h"
|
||||||
|
U_CDECL_END
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
|
@ -33,6 +33,7 @@ if test "$PHP_INTL" != "no"; then
|
||||||
collator/collator_error.c \
|
collator/collator_error.c \
|
||||||
common/common_error.c \
|
common/common_error.c \
|
||||||
common/common_enum.cpp \
|
common/common_enum.cpp \
|
||||||
|
common/common_date.cpp \
|
||||||
formatter/formatter.c \
|
formatter/formatter.c \
|
||||||
formatter/formatter_main.c \
|
formatter/formatter_main.c \
|
||||||
formatter/formatter_class.c \
|
formatter/formatter_class.c \
|
||||||
|
@ -51,6 +52,7 @@ if test "$PHP_INTL" != "no"; then
|
||||||
dateformat/dateformat_attr.c \
|
dateformat/dateformat_attr.c \
|
||||||
dateformat/dateformat_data.c \
|
dateformat/dateformat_data.c \
|
||||||
dateformat/dateformat_format.c \
|
dateformat/dateformat_format.c \
|
||||||
|
dateformat/dateformat_format_object.cpp \
|
||||||
dateformat/dateformat_parse.c \
|
dateformat/dateformat_parse.c \
|
||||||
dateformat/dateformat_create.cpp \
|
dateformat/dateformat_create.cpp \
|
||||||
dateformat/dateformat_attrcpp.cpp \
|
dateformat/dateformat_attrcpp.cpp \
|
||||||
|
|
|
@ -24,6 +24,7 @@ if (PHP_INTL != "no") {
|
||||||
ADD_SOURCES(configure_module_dirname + "/common", "\
|
ADD_SOURCES(configure_module_dirname + "/common", "\
|
||||||
common_error.c \
|
common_error.c \
|
||||||
common_enum.cpp \
|
common_enum.cpp \
|
||||||
|
common_date.cpp \
|
||||||
", "intl");
|
", "intl");
|
||||||
ADD_SOURCES(configure_module_dirname + "/formatter", "\
|
ADD_SOURCES(configure_module_dirname + "/formatter", "\
|
||||||
formatter.c \
|
formatter.c \
|
||||||
|
@ -61,6 +62,7 @@ if (PHP_INTL != "no") {
|
||||||
dateformat_class.c \
|
dateformat_class.c \
|
||||||
dateformat_attr.c \
|
dateformat_attr.c \
|
||||||
dateformat_format.c \
|
dateformat_format.c \
|
||||||
|
dateformat_format_object.cpp \
|
||||||
dateformat_parse.c \
|
dateformat_parse.c \
|
||||||
dateformat_data.c \
|
dateformat_data.c \
|
||||||
dateformat_attrcpp.cpp \
|
dateformat_attrcpp.cpp \
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "php_intl.h"
|
#include "php_intl.h"
|
||||||
#include "dateformat_data.h"
|
#include "dateformat_data.h"
|
||||||
#include "dateformat_format.h"
|
#include "dateformat_format.h"
|
||||||
|
#include "dateformat_format_object.h"
|
||||||
#include "dateformat_parse.h"
|
#include "dateformat_parse.h"
|
||||||
#include "dateformat.h"
|
#include "dateformat.h"
|
||||||
#include "dateformat_attr.h"
|
#include "dateformat_attr.h"
|
||||||
|
@ -121,6 +122,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_intldateformatter_format, 0, 0, 0)
|
||||||
ZEND_ARG_INFO(0, array)
|
ZEND_ARG_INFO(0, array)
|
||||||
ZEND_END_ARG_INFO()
|
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_BEGIN_ARG_INFO(arginfo_intldateformatter_getdatetype, 0)
|
||||||
ZEND_END_ARG_INFO()
|
ZEND_END_ARG_INFO()
|
||||||
|
|
||||||
|
@ -171,6 +178,7 @@ static zend_function_entry IntlDateFormatter_class_functions[] = {
|
||||||
PHP_NAMED_FE( setLenient, ZEND_FN( datefmt_set_lenient ), arginfo_intldateformatter_setlenient )
|
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( isLenient, ZEND_FN( datefmt_is_lenient ), arginfo_intldateformatter_getdatetype )
|
||||||
PHP_NAMED_FE( format, ZEND_FN( datefmt_format ), arginfo_intldateformatter_format )
|
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( parse, ZEND_FN( datefmt_parse), datefmt_parse_args )
|
||||||
PHP_NAMED_FE( localtime, ZEND_FN( datefmt_localtime ), 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 )
|
PHP_NAMED_FE( getErrorCode, ZEND_FN( datefmt_get_error_code ), arginfo_intldateformatter_getdatetype )
|
||||||
|
|
|
@ -21,15 +21,13 @@
|
||||||
#include <unicode/ustring.h>
|
#include <unicode/ustring.h>
|
||||||
#include <unicode/ucal.h>
|
#include <unicode/ucal.h>
|
||||||
|
|
||||||
#include "php_intl.h"
|
#include "../php_intl.h"
|
||||||
#include "intl_convert.h"
|
#include "../intl_convert.h"
|
||||||
|
#include "../common/common_date.h"
|
||||||
#include "dateformat.h"
|
#include "dateformat.h"
|
||||||
#include "dateformat_class.h"
|
#include "dateformat_class.h"
|
||||||
#include "dateformat_format.h"
|
#include "dateformat_format.h"
|
||||||
#include "dateformat_data.h"
|
#include "dateformat_data.h"
|
||||||
/* avoid redefinition of int8_t, already defined in unicode/pwin32.h */
|
|
||||||
#define _MSC_STDINT_H_ 1
|
|
||||||
#include "ext/date/php_date.h"
|
|
||||||
|
|
||||||
/* {{{
|
/* {{{
|
||||||
* Internal function which calls the udat_format
|
* Internal function which calls the udat_format
|
||||||
|
@ -61,20 +59,38 @@ static void internal_format(IntlDateFormatter_object *dfo, UDate timestamp, zval
|
||||||
/* {{{
|
/* {{{
|
||||||
* Internal function which fetches an element from the passed array for the key_name passed
|
* Internal function which fetches an element from the passed array for the key_name passed
|
||||||
*/
|
*/
|
||||||
static double internal_get_arr_ele(IntlDateFormatter_object *dfo, HashTable* hash_arr, char* key_name TSRMLS_DC)
|
static int32_t internal_get_arr_ele(IntlDateFormatter_object *dfo,
|
||||||
|
HashTable* hash_arr, char* key_name, intl_error *err TSRMLS_DC)
|
||||||
{
|
{
|
||||||
zval** ele_value = NULL;
|
zval **ele_value = NULL;
|
||||||
UDate result = -1;
|
int32_t result = 0;
|
||||||
|
char *message;
|
||||||
|
|
||||||
if( zend_hash_find( hash_arr, key_name, strlen(key_name) + 1, (void **)&ele_value ) == SUCCESS ){
|
if (U_FAILURE(err->code)) {
|
||||||
if( Z_TYPE_PP(ele_value)!= IS_LONG ){
|
return result;
|
||||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
|
}
|
||||||
"datefmt_format: parameter array does not contain a long element.", 0 TSRMLS_CC );
|
|
||||||
}else{
|
if (zend_hash_find(hash_arr, key_name, strlen(key_name) + 1,
|
||||||
result = Z_LVAL_PP(ele_value);
|
(void **)&ele_value) == SUCCESS) {
|
||||||
|
if(Z_TYPE_PP(ele_value) != IS_LONG) {
|
||||||
|
spprintf(&message, 0, "datefmt_format: parameter array contains "
|
||||||
|
"a non-integer element for key '%s'", key_name);
|
||||||
|
intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, message, 1 TSRMLS_CC);
|
||||||
|
efree(message);
|
||||||
|
} else {
|
||||||
|
if (Z_LVAL_PP(ele_value) > INT32_MAX ||
|
||||||
|
Z_LVAL_PP(ele_value) < INT32_MIN) {
|
||||||
|
spprintf(&message, 0, "datefmt_format: value %ld is out of "
|
||||||
|
"bounds for a 32-bit integer in key '%s'",
|
||||||
|
Z_LVAL_PP(ele_value), key_name);
|
||||||
|
intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR, message, 1 TSRMLS_CC);
|
||||||
|
efree(message);
|
||||||
|
} else {
|
||||||
|
result = Z_LVAL_PP(ele_value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* printf("\n Inside internal_get_arr_ele key_name= %s, result = %g \n", key_name, result); */
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -82,41 +98,49 @@ static double internal_get_arr_ele(IntlDateFormatter_object *dfo, HashTable* has
|
||||||
/* {{{
|
/* {{{
|
||||||
* Internal function which sets UCalendar from the passed array and retrieves timestamp
|
* Internal function which sets UCalendar from the passed array and retrieves timestamp
|
||||||
*/
|
*/
|
||||||
static UDate internal_get_timestamp(IntlDateFormatter_object *dfo, HashTable* hash_arr TSRMLS_DC)
|
static UDate internal_get_timestamp(IntlDateFormatter_object *dfo,
|
||||||
|
HashTable *hash_arr TSRMLS_DC)
|
||||||
{
|
{
|
||||||
long year =0;
|
int32_t year,
|
||||||
long month =0;
|
month,
|
||||||
long hour =0;
|
hour,
|
||||||
long minute =0;
|
minute,
|
||||||
long second =0;
|
second,
|
||||||
long wday =0;
|
mday;
|
||||||
long yday =0;
|
UCalendar *pcal;
|
||||||
long mday =0;
|
intl_error *err = &dfo->datef_data.error;
|
||||||
UBool isInDST = FALSE;
|
|
||||||
const UCalendar *pcal;
|
#define INTL_GET_ELEM(elem) \
|
||||||
|
internal_get_arr_ele(dfo, hash_arr, (elem), err TSRMLS_CC)
|
||||||
|
|
||||||
/* Fetch values from the incoming array */
|
/* Fetch values from the incoming array */
|
||||||
year = internal_get_arr_ele( dfo, hash_arr, CALENDAR_YEAR TSRMLS_CC) + 1900; /* tm_year is years since 1900 */
|
year = INTL_GET_ELEM(CALENDAR_YEAR) + 1900; /* tm_year is years since 1900 */
|
||||||
/* Month in ICU and PHP starts from January =0 */
|
/* Month in ICU and PHP starts from January =0 */
|
||||||
month = internal_get_arr_ele( dfo, hash_arr, CALENDAR_MON TSRMLS_CC);
|
month = INTL_GET_ELEM(CALENDAR_MON);
|
||||||
hour = internal_get_arr_ele( dfo, hash_arr, CALENDAR_HOUR TSRMLS_CC);
|
hour = INTL_GET_ELEM(CALENDAR_HOUR);
|
||||||
minute = internal_get_arr_ele( dfo, hash_arr, CALENDAR_MIN TSRMLS_CC);
|
minute = INTL_GET_ELEM(CALENDAR_MIN);
|
||||||
second = internal_get_arr_ele( dfo, hash_arr, CALENDAR_SEC TSRMLS_CC);
|
second = INTL_GET_ELEM(CALENDAR_SEC);
|
||||||
wday = internal_get_arr_ele( dfo, hash_arr, CALENDAR_WDAY TSRMLS_CC);
|
|
||||||
yday = internal_get_arr_ele( dfo, hash_arr, CALENDAR_YDAY TSRMLS_CC);
|
|
||||||
isInDST = internal_get_arr_ele( dfo, hash_arr, CALENDAR_ISDST TSRMLS_CC);
|
|
||||||
/* For the ucal_setDateTime() function, this is the 'date' value */
|
/* For the ucal_setDateTime() function, this is the 'date' value */
|
||||||
mday = internal_get_arr_ele( dfo, hash_arr, CALENDAR_MDAY TSRMLS_CC);
|
mday = INTL_GET_ELEM(CALENDAR_MDAY);
|
||||||
|
|
||||||
pcal = udat_getCalendar(DATE_FORMAT_OBJECT(dfo));
|
#undef INTL_GET_ELEM
|
||||||
/* set the incoming values for the calendar */
|
|
||||||
ucal_setDateTime( pcal, year, month, mday, hour, minute, second, &INTL_DATA_ERROR_CODE(dfo));
|
pcal = ucal_clone(udat_getCalendar(DATE_FORMAT_OBJECT(dfo)),
|
||||||
if( INTL_DATA_ERROR_CODE(dfo) != U_ZERO_ERROR){
|
&INTL_DATA_ERROR_CODE(dfo));
|
||||||
|
|
||||||
|
if (INTL_DATA_ERROR_CODE(dfo) != U_ZERO_ERROR) {
|
||||||
|
intl_errors_set(err, INTL_DATA_ERROR_CODE(dfo), "datefmt_format: "
|
||||||
|
"error cloning calendar", 0 TSRMLS_CC);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* set the incoming values for the calendar */
|
||||||
|
ucal_setDateTime(pcal, year, month, mday, hour, minute, second, &INTL_DATA_ERROR_CODE(dfo));
|
||||||
|
/* actually, ucal_setDateTime cannot fail */
|
||||||
|
|
||||||
/* Fetch the timestamp from the UCalendar */
|
/* Fetch the timestamp from the UCalendar */
|
||||||
return ucal_getMillis(pcal, &INTL_DATA_ERROR_CODE(dfo) );
|
return ucal_getMillis(pcal, &INTL_DATA_ERROR_CODE(dfo));
|
||||||
|
udat_close(pcal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,70 +150,39 @@ static UDate internal_get_timestamp(IntlDateFormatter_object *dfo, HashTable* ha
|
||||||
* Format the time value as a string. }}}*/
|
* Format the time value as a string. }}}*/
|
||||||
PHP_FUNCTION(datefmt_format)
|
PHP_FUNCTION(datefmt_format)
|
||||||
{
|
{
|
||||||
UDate timestamp =0;
|
UDate timestamp = 0;
|
||||||
UDate p_timestamp =0;
|
HashTable *hash_arr = NULL;
|
||||||
HashTable* hash_arr = NULL;
|
zval *zarg = NULL;
|
||||||
zval* zarg = NULL;
|
|
||||||
|
|
||||||
DATE_FORMAT_METHOD_INIT_VARS;
|
DATE_FORMAT_METHOD_INIT_VARS;
|
||||||
|
|
||||||
/* Parse parameters. */
|
/* Parse parameters. */
|
||||||
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz", &object, IntlDateFormatter_ce_ptr,&zarg ) == FAILURE )
|
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz",
|
||||||
{
|
&object, IntlDateFormatter_ce_ptr, &zarg) == FAILURE) {
|
||||||
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format: unable to parse input params", 0 TSRMLS_CC );
|
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format: unable "
|
||||||
|
"to parse input params", 0 TSRMLS_CC );
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fetch the object. */
|
|
||||||
DATE_FORMAT_METHOD_FETCH_OBJECT;
|
DATE_FORMAT_METHOD_FETCH_OBJECT;
|
||||||
|
|
||||||
switch(Z_TYPE_P(zarg) ){
|
if (Z_TYPE_P(zarg) == IS_ARRAY) {
|
||||||
case IS_LONG:
|
hash_arr = Z_ARRVAL_P(zarg);
|
||||||
p_timestamp = Z_LVAL_P(zarg) ;
|
if (!hash_arr || zend_hash_num_elements(hash_arr) == 0) {
|
||||||
timestamp = p_timestamp * 1000;
|
|
||||||
break;
|
|
||||||
case IS_DOUBLE:
|
|
||||||
/* timestamp*1000 since ICU expects it in milliseconds */
|
|
||||||
p_timestamp = Z_DVAL_P(zarg) ;
|
|
||||||
timestamp = p_timestamp * 1000;
|
|
||||||
break;
|
|
||||||
case IS_ARRAY:
|
|
||||||
hash_arr = Z_ARRVAL_P(zarg);
|
|
||||||
if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 )
|
|
||||||
RETURN_FALSE;
|
|
||||||
|
|
||||||
timestamp = internal_get_timestamp(dfo, hash_arr TSRMLS_CC);
|
|
||||||
INTL_METHOD_CHECK_STATUS( dfo, "datefmt_format: Date formatting failed" )
|
|
||||||
break;
|
|
||||||
case IS_OBJECT: {
|
|
||||||
zend_class_entry *date_ce = php_date_get_date_ce();
|
|
||||||
zval retval;
|
|
||||||
zval *zfuncname;
|
|
||||||
if(!instanceof_function(Z_OBJCE_P(zarg), date_ce TSRMLS_CC)) {
|
|
||||||
intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format: object must be an instance of DateTime", 0 TSRMLS_CC );
|
|
||||||
RETURN_FALSE;
|
|
||||||
}
|
|
||||||
INIT_ZVAL(retval);
|
|
||||||
MAKE_STD_ZVAL(zfuncname);
|
|
||||||
ZVAL_STRING(zfuncname, "getTimestamp", 1);
|
|
||||||
if(call_user_function(NULL, &zarg, zfuncname, &retval, 0, NULL TSRMLS_CC) != SUCCESS || Z_TYPE(retval) != IS_LONG) {
|
|
||||||
intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format: cannot get timestamp", 0 TSRMLS_CC );
|
|
||||||
zval_ptr_dtor(&zfuncname);
|
|
||||||
RETURN_FALSE;
|
|
||||||
}
|
|
||||||
zval_ptr_dtor(&zfuncname);
|
|
||||||
p_timestamp = Z_LVAL(retval);
|
|
||||||
timestamp = p_timestamp*1000;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
intl_errors_set( INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR,
|
|
||||||
"datefmt_format: takes either an array or an integer timestamp value or a DateTime object", 0 TSRMLS_CC );
|
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal_format( dfo, timestamp, return_value TSRMLS_CC);
|
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_P(dfo),
|
||||||
|
"datefmt_format" TSRMLS_CC);
|
||||||
|
if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_format( dfo, timestamp, return_value TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
230
ext/intl/dateformat/dateformat_format_object.cpp
Normal file
230
ext/intl/dateformat/dateformat_format_object.cpp
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| 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;
|
||||||
|
}
|
19
ext/intl/dateformat/dateformat_format_object.h
Normal file
19
ext/intl/dateformat/dateformat_format_object.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| 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);
|
|
@ -31,6 +31,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../intl_convertcpp.h"
|
#include "../intl_convertcpp.h"
|
||||||
|
#include "../common/common_date.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "php_intl.h"
|
#include "php_intl.h"
|
||||||
|
@ -38,23 +39,10 @@ extern "C" {
|
||||||
#include "msgformat_format.h"
|
#include "msgformat_format.h"
|
||||||
#include "msgformat_helpers.h"
|
#include "msgformat_helpers.h"
|
||||||
#include "intl_convert.h"
|
#include "intl_convert.h"
|
||||||
#define USE_CALENDAR_POINTER 1
|
|
||||||
#include "../calendar/calendar_class.h"
|
|
||||||
/* avoid redefinition of int8_t, already defined in unicode/pwin32.h */
|
|
||||||
#define _MSC_STDINT_H_ 1
|
|
||||||
#include "ext/date/php_date.h"
|
|
||||||
#define USE_TIMEZONE_POINTER
|
#define USE_TIMEZONE_POINTER
|
||||||
#include "../timezone/timezone_class.h"
|
#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
|
#if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 48
|
||||||
#define HAS_MESSAGE_PATTERN 1
|
#define HAS_MESSAGE_PATTERN 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -95,66 +83,6 @@ U_CFUNC int32_t umsg_format_arg_count(UMessageFormat *fmt)
|
||||||
return fmt_count;
|
return fmt_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double umsg_helper_zval_to_millis(zval *z, UErrorCode *status TSRMLS_DC) {
|
|
||||||
double rv = NAN;
|
|
||||||
long lv;
|
|
||||||
int type;
|
|
||||||
|
|
||||||
if (U_FAILURE(*status)) {
|
|
||||||
return NAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (Z_TYPE_P(z)) {
|
|
||||||
case IS_STRING:
|
|
||||||
type = is_numeric_string(Z_STRVAL_P(z), Z_STRLEN_P(z), &lv, &rv, 0);
|
|
||||||
if (type == IS_DOUBLE) {
|
|
||||||
rv *= U_MILLIS_PER_SECOND;
|
|
||||||
} else if (type == IS_LONG) {
|
|
||||||
rv = U_MILLIS_PER_SECOND * (double)lv;
|
|
||||||
} else {
|
|
||||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case IS_LONG:
|
|
||||||
rv = U_MILLIS_PER_SECOND * (double)Z_LVAL_P(z);
|
|
||||||
break;
|
|
||||||
case IS_DOUBLE:
|
|
||||||
rv = U_MILLIS_PER_SECOND * Z_DVAL_P(z);
|
|
||||||
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);
|
|
||||||
} 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;
|
|
||||||
} else {
|
|
||||||
rv = (double)co->ucal->getTime(*status);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* TODO: try with cast(), get() to obtain a number */
|
|
||||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HashTable *umsg_get_numeric_types(MessageFormatter_object *mfo,
|
static HashTable *umsg_get_numeric_types(MessageFormatter_object *mfo,
|
||||||
intl_error& err TSRMLS_DC)
|
intl_error& err TSRMLS_DC)
|
||||||
{
|
{
|
||||||
|
@ -613,7 +541,7 @@ retry_kint64:
|
||||||
}
|
}
|
||||||
case Formattable::kDate:
|
case Formattable::kDate:
|
||||||
{
|
{
|
||||||
double dd = umsg_helper_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)) {
|
if (U_FAILURE(err.code)) {
|
||||||
char *message, *key_char;
|
char *message, *key_char;
|
||||||
int key_len;
|
int key_len;
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
#include "dateformat/dateformat_attr.h"
|
#include "dateformat/dateformat_attr.h"
|
||||||
#include "dateformat/dateformat_attrcpp.h"
|
#include "dateformat/dateformat_attrcpp.h"
|
||||||
#include "dateformat/dateformat_format.h"
|
#include "dateformat/dateformat_format.h"
|
||||||
|
#include "dateformat/dateformat_format_object.h"
|
||||||
#include "dateformat/dateformat_parse.h"
|
#include "dateformat/dateformat_parse.h"
|
||||||
#include "dateformat/dateformat_data.h"
|
#include "dateformat/dateformat_data.h"
|
||||||
|
|
||||||
|
@ -350,6 +351,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_datefmt_format, 0, 0, 0)
|
||||||
ZEND_ARG_INFO(0, array)
|
ZEND_ARG_INFO(0, array)
|
||||||
ZEND_END_ARG_INFO()
|
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_BEGIN_ARG_INFO_EX(arginfo_datefmt_create, 0, 0, 3)
|
||||||
ZEND_ARG_INFO(0, locale)
|
ZEND_ARG_INFO(0, locale)
|
||||||
ZEND_ARG_INFO(0, date_type)
|
ZEND_ARG_INFO(0, date_type)
|
||||||
|
@ -706,6 +714,7 @@ zend_function_entry intl_functions[] = {
|
||||||
PHP_FE( datefmt_is_lenient, arginfo_msgfmt_get_locale )
|
PHP_FE( datefmt_is_lenient, arginfo_msgfmt_get_locale )
|
||||||
PHP_FE( datefmt_set_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, arginfo_datefmt_format )
|
||||||
|
PHP_FE( datefmt_format_object, arginfo_datefmt_format_object )
|
||||||
PHP_FE( datefmt_parse, datefmt_parse_args )
|
PHP_FE( datefmt_parse, datefmt_parse_args )
|
||||||
PHP_FE( datefmt_localtime , datefmt_parse_args )
|
PHP_FE( datefmt_localtime , datefmt_parse_args )
|
||||||
PHP_FE( datefmt_get_error_code, arginfo_msgfmt_get_error_code )
|
PHP_FE( datefmt_get_error_code, arginfo_msgfmt_get_error_code )
|
||||||
|
|
|
@ -399,24 +399,24 @@ Formatted DateTime is : 20001230 05:04 PM
|
||||||
Date is: stdClass::__set_state(array(
|
Date is: stdClass::__set_state(array(
|
||||||
))
|
))
|
||||||
------------
|
------------
|
||||||
Error while formatting as: 'datefmt_format: object must be an instance of DateTime: 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(
|
Date is: stdClass::__set_state(array(
|
||||||
))
|
))
|
||||||
------------
|
------------
|
||||||
Error while formatting as: 'datefmt_format: object must be an instance of DateTime: 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(
|
Date is: stdClass::__set_state(array(
|
||||||
))
|
))
|
||||||
------------
|
------------
|
||||||
Error while formatting as: 'datefmt_format: object must be an instance of DateTime: 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(
|
Date is: stdClass::__set_state(array(
|
||||||
))
|
))
|
||||||
------------
|
------------
|
||||||
Error while formatting as: 'datefmt_format: object must be an instance of DateTime: 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(
|
Date is: stdClass::__set_state(array(
|
||||||
))
|
))
|
||||||
------------
|
------------
|
||||||
Error while formatting as: 'datefmt_format: object must be an instance of DateTime: 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'
|
||||||
|
|
41
ext/intl/tests/dateformat_formatObject_calendar.phpt
Normal file
41
ext/intl/tests/dateformat_formatObject_calendar.phpt
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
--TEST--
|
||||||
|
IntlDateFormatter::formatObject(): IntlCalendar tests
|
||||||
|
--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", "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==
|
||||||
|
|
||||||
|
--EXPECT--
|
||||||
|
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==
|
||||||
|
|
34
ext/intl/tests/dateformat_formatObject_datetime.phpt
Normal file
34
ext/intl/tests/dateformat_formatObject_datetime.phpt
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
--TEST--
|
||||||
|
IntlDateFormatter::formatObject(): DateTime tests
|
||||||
|
--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", "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==
|
||||||
|
|
||||||
|
--EXPECT--
|
||||||
|
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==
|
||||||
|
|
74
ext/intl/tests/dateformat_formatObject_error.phpt
Normal file
74
ext/intl/tests/dateformat_formatObject_error.phpt
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
--TEST--
|
||||||
|
IntlDateFormatter::formatObject(): error conditions
|
||||||
|
--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", "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==
|
||||||
|
|
||||||
|
--EXPECTF--
|
||||||
|
|
||||||
|
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==
|
||||||
|
|
|
@ -20,6 +20,7 @@ $mf = new MessageFormatter('en_US', $fmt);
|
||||||
var_dump($mf->format(array("foo" => new stdclass())));
|
var_dump($mf->format(array("foo" => new stdclass())));
|
||||||
|
|
||||||
--EXPECTF--
|
--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
|
Warning: MessageFormatter::format(): The argument for key 'foo' cannot be used as a date or time in %s on line %d
|
||||||
bool(false)
|
bool(false)
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include <unicode/calendar.h>
|
#include <unicode/calendar.h>
|
||||||
#include "../intl_convertcpp.h"
|
#include "../intl_convertcpp.h"
|
||||||
|
|
||||||
|
#include "../common/common_date.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "../intl_convert.h"
|
#include "../intl_convert.h"
|
||||||
#define USE_TIMEZONE_POINTER 1
|
#define USE_TIMEZONE_POINTER 1
|
||||||
|
@ -54,79 +56,6 @@ U_CFUNC void timezone_object_construct(const TimeZone *zone, zval *object, int o
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ 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
|
/* {{{ timezone_convert_to_datetimezone
|
||||||
* Convert from TimeZone to DateTimeZone object */
|
* Convert from TimeZone to DateTimeZone object */
|
||||||
U_CFUNC zval *timezone_convert_to_datetimezone(const TimeZone *timeZone,
|
U_CFUNC zval *timezone_convert_to_datetimezone(const TimeZone *timeZone,
|
||||||
|
|
|
@ -59,7 +59,6 @@ typedef struct {
|
||||||
RETURN_FALSE; \
|
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);
|
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);
|
TimeZone *timezone_process_timezone_argument(zval **zv_timezone, intl_error *error, const char *func TSRMLS_DC);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
#include <unicode/timezone.h>
|
#include <unicode/timezone.h>
|
||||||
#include <unicode/ustring.h>
|
#include <unicode/ustring.h>
|
||||||
#include "intl_convertcpp.h"
|
#include "intl_convertcpp.h"
|
||||||
|
|
||||||
|
#include "../common/common_date.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "../php_intl.h"
|
#include "../php_intl.h"
|
||||||
#define USE_TIMEZONE_POINTER 1
|
#define USE_TIMEZONE_POINTER 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue