Skip to content

Commit 2416719

Browse files
committed
Unified zval -> UDate conversions
Now IntlDateFormatter::format() also accepts IntlCalendar objects. Code is shared in MessageFormatter and IntlDateFormatter.
1 parent 758f068 commit 2416719

8 files changed

Lines changed: 149 additions & 129 deletions

File tree

ext/intl/common/common_date.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| PHP Version 5 |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.php.net/license/3_01.txt |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| license@php.net so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: Gustavo Lopes <cataphract@php.net> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#include "../intl_cppshims.h"
18+
19+
#include <unicode/calendar.h>
20+
21+
extern "C" {
22+
#include "../php_intl.h"
23+
#define USE_CALENDAR_POINTER 1
24+
#include "../calendar/calendar_class.h"
25+
#include <ext/date/php_date.h>
26+
}
27+
28+
U_CFUNC double intl_zval_to_millis(zval *z, UErrorCode *status TSRMLS_DC)
29+
{
30+
double rv = NAN;
31+
long lv;
32+
int type;
33+
34+
if (U_FAILURE(*status)) {
35+
return NAN;
36+
}
37+
38+
switch (Z_TYPE_P(z)) {
39+
case IS_STRING:
40+
type = is_numeric_string(Z_STRVAL_P(z), Z_STRLEN_P(z), &lv, &rv, 0);
41+
if (type == IS_DOUBLE) {
42+
rv *= U_MILLIS_PER_SECOND;
43+
} else if (type == IS_LONG) {
44+
rv = U_MILLIS_PER_SECOND * (double)lv;
45+
} else {
46+
*status = U_ILLEGAL_ARGUMENT_ERROR;
47+
}
48+
break;
49+
case IS_LONG:
50+
rv = U_MILLIS_PER_SECOND * (double)Z_LVAL_P(z);
51+
break;
52+
case IS_DOUBLE:
53+
rv = U_MILLIS_PER_SECOND * Z_DVAL_P(z);
54+
break;
55+
case IS_OBJECT:
56+
if (instanceof_function(Z_OBJCE_P(z), php_date_get_date_ce() TSRMLS_CC)) {
57+
zval retval;
58+
zval *zfuncname;
59+
INIT_ZVAL(retval);
60+
MAKE_STD_ZVAL(zfuncname);
61+
ZVAL_STRING(zfuncname, "getTimestamp", 1);
62+
if (call_user_function(NULL, &(z), zfuncname, &retval, 0, NULL TSRMLS_CC)
63+
!= SUCCESS || Z_TYPE(retval) != IS_LONG) {
64+
*status = U_INTERNAL_PROGRAM_ERROR;
65+
} else {
66+
rv = U_MILLIS_PER_SECOND * (double)Z_LVAL(retval);
67+
}
68+
zval_ptr_dtor(&zfuncname);
69+
} else if (instanceof_function(Z_OBJCE_P(z), Calendar_ce_ptr TSRMLS_CC)) {
70+
Calendar_object *co = (Calendar_object *)
71+
zend_object_store_get_object(z TSRMLS_CC );
72+
if (co->ucal == NULL) {
73+
*status = U_ILLEGAL_ARGUMENT_ERROR;
74+
} else {
75+
rv = (double)co->ucal->getTime(*status);
76+
}
77+
} else {
78+
/* TODO: try with cast(), get() to obtain a number */
79+
*status = U_ILLEGAL_ARGUMENT_ERROR;
80+
}
81+
break;
82+
default:
83+
*status = U_ILLEGAL_ARGUMENT_ERROR;
84+
}
85+
86+
return rv;
87+
}
88+

ext/intl/common/common_date.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| PHP Version 5 |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.php.net/license/3_01.txt |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| license@php.net so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: Gustavo Lopes <cataphract@php.net> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#ifndef COMMON_DATE_H
18+
#define COMMON_DATE_H
19+
20+
#include <unicode/umachine.h>
21+
22+
U_CDECL_BEGIN
23+
#include <php.h>
24+
U_CDECL_END
25+
26+
U_CFUNC double intl_zval_to_millis(zval *z, UErrorCode *status TSRMLS_DC);
27+
28+
#endif /* COMMON_DATE_H */
29+

ext/intl/config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ if test "$PHP_INTL" != "no"; then
3333
collator/collator_error.c \
3434
common/common_error.c \
3535
common/common_enum.cpp \
36+
common/common_date.cpp \
3637
formatter/formatter.c \
3738
formatter/formatter_main.c \
3839
formatter/formatter_class.c \

ext/intl/config.w32

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ if (PHP_INTL != "no") {
2424
ADD_SOURCES(configure_module_dirname + "/common", "\
2525
common_error.c \
2626
common_enum.cpp \
27+
common_date.cpp \
2728
", "intl");
2829
ADD_SOURCES(configure_module_dirname + "/formatter", "\
2930
formatter.c \

ext/intl/dateformat/dateformat.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,5 @@ These are not necessary at this point of time
4040
#define CALENDAR_YEAR "tm_year"
4141
#define CALENDAR_WDAY "tm_wday"
4242
#define CALENDAR_YDAY "tm_yday"
43-
#define CALENDAR_ISDST "tm_isdst"
4443

4544
#endif // DATE_FORMATTER_H

ext/intl/dateformat/dateformat_format.c

Lines changed: 23 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,13 @@
2121
#include <unicode/ustring.h>
2222
#include <unicode/ucal.h>
2323

24-
#include "php_intl.h"
25-
#include "intl_convert.h"
24+
#include "../php_intl.h"
25+
#include "../intl_convert.h"
26+
#include "../common/common_date.h"
2627
#include "dateformat.h"
2728
#include "dateformat_class.h"
2829
#include "dateformat_format.h"
2930
#include "dateformat_data.h"
30-
/* avoid redefinition of int8_t, already defined in unicode/pwin32.h */
31-
#define _MSC_STDINT_H_ 1
32-
#include "ext/date/php_date.h"
3331

3432
/* {{{
3533
* Internal function which calls the udat_format
@@ -126,70 +124,38 @@ static UDate internal_get_timestamp(IntlDateFormatter_object *dfo, HashTable* ha
126124
* Format the time value as a string. }}}*/
127125
PHP_FUNCTION(datefmt_format)
128126
{
129-
UDate timestamp =0;
130-
UDate p_timestamp =0;
131-
HashTable* hash_arr = NULL;
132-
zval* zarg = NULL;
127+
UDate timestamp = 0;
128+
HashTable *hash_arr = NULL;
129+
zval *zarg = NULL;
133130

134131
DATE_FORMAT_METHOD_INIT_VARS;
135132

136133
/* Parse parameters. */
137-
if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz", &object, IntlDateFormatter_ce_ptr,&zarg ) == FAILURE )
138-
{
139-
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format: unable to parse input params", 0 TSRMLS_CC );
134+
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz",
135+
&object, IntlDateFormatter_ce_ptr, &zarg) == FAILURE) {
136+
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format: unable "
137+
"to parse input params", 0 TSRMLS_CC );
140138
RETURN_FALSE;
141139
}
142140

143-
/* Fetch the object. */
144141
DATE_FORMAT_METHOD_FETCH_OBJECT;
145142

146-
switch(Z_TYPE_P(zarg) ){
147-
case IS_LONG:
148-
p_timestamp = Z_LVAL_P(zarg) ;
149-
timestamp = p_timestamp * 1000;
150-
break;
151-
case IS_DOUBLE:
152-
/* timestamp*1000 since ICU expects it in milliseconds */
153-
p_timestamp = Z_DVAL_P(zarg) ;
154-
timestamp = p_timestamp * 1000;
155-
break;
156-
case IS_ARRAY:
157-
hash_arr = Z_ARRVAL_P(zarg);
158-
if( !hash_arr || zend_hash_num_elements( hash_arr ) == 0 )
159-
RETURN_FALSE;
160-
161-
timestamp = internal_get_timestamp(dfo, hash_arr TSRMLS_CC);
162-
INTL_METHOD_CHECK_STATUS( dfo, "datefmt_format: Date formatting failed" )
163-
break;
164-
case IS_OBJECT: {
165-
zend_class_entry *date_ce = php_date_get_date_ce();
166-
zval retval;
167-
zval *zfuncname;
168-
if(!instanceof_function(Z_OBJCE_P(zarg), date_ce TSRMLS_CC)) {
169-
intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format: object must be an instance of DateTime", 0 TSRMLS_CC );
170-
RETURN_FALSE;
171-
}
172-
INIT_ZVAL(retval);
173-
MAKE_STD_ZVAL(zfuncname);
174-
ZVAL_STRING(zfuncname, "getTimestamp", 1);
175-
if(call_user_function(NULL, &zarg, zfuncname, &retval, 0, NULL TSRMLS_CC) != SUCCESS || Z_TYPE(retval) != IS_LONG) {
176-
intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format: cannot get timestamp", 0 TSRMLS_CC );
177-
zval_ptr_dtor(&zfuncname);
178-
RETURN_FALSE;
179-
}
180-
zval_ptr_dtor(&zfuncname);
181-
p_timestamp = Z_LVAL(retval);
182-
timestamp = p_timestamp*1000;
183-
}
184-
break;
185-
default:
186-
intl_errors_set( INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR,
187-
"datefmt_format: takes either an array or an integer timestamp value or a DateTime object", 0 TSRMLS_CC );
143+
if (Z_TYPE_P(zarg) == IS_ARRAY) {
144+
hash_arr = Z_ARRVAL_P(zarg);
145+
if (!hash_arr || zend_hash_num_elements(hash_arr) == 0) {
188146
RETURN_FALSE;
189-
}
147+
}
190148

191-
internal_format( dfo, timestamp, return_value TSRMLS_CC);
149+
timestamp = internal_get_timestamp(dfo, hash_arr TSRMLS_CC);
150+
INTL_METHOD_CHECK_STATUS(dfo, "datefmt_format: date formatting failed")
151+
} else {
152+
timestamp = intl_zval_to_millis(zarg,
153+
&INTL_DATA_ERROR_CODE(dfo) TSRMLS_CC);
154+
INTL_METHOD_CHECK_STATUS(dfo, "datefmt_format: could not convert input "
155+
"into a date")
156+
}
192157

158+
internal_format( dfo, timestamp, return_value TSRMLS_CC);
193159
}
194160

195161
/* }}} */

ext/intl/msgformat/msgformat_helpers.cpp

Lines changed: 2 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,14 @@
3131
#include <vector>
3232

3333
#include "../intl_convertcpp.h"
34+
#include "../common/common_date.h"
3435

3536
extern "C" {
3637
#include "php_intl.h"
3738
#include "msgformat_class.h"
3839
#include "msgformat_format.h"
3940
#include "msgformat_helpers.h"
4041
#include "intl_convert.h"
41-
#define USE_CALENDAR_POINTER 1
42-
#include "../calendar/calendar_class.h"
43-
/* avoid redefinition of int8_t, already defined in unicode/pwin32.h */
44-
#define _MSC_STDINT_H_ 1
45-
#include "ext/date/php_date.h"
4642
#define USE_TIMEZONE_POINTER
4743
#include "../timezone/timezone_class.h"
4844
}
@@ -95,66 +91,6 @@ U_CFUNC int32_t umsg_format_arg_count(UMessageFormat *fmt)
9591
return fmt_count;
9692
}
9793

98-
static double umsg_helper_zval_to_millis(zval *z, UErrorCode *status TSRMLS_DC) {
99-
double rv = NAN;
100-
long lv;
101-
int type;
102-
103-
if (U_FAILURE(*status)) {
104-
return NAN;
105-
}
106-
107-
switch (Z_TYPE_P(z)) {
108-
case IS_STRING:
109-
type = is_numeric_string(Z_STRVAL_P(z), Z_STRLEN_P(z), &lv, &rv, 0);
110-
if (type == IS_DOUBLE) {
111-
rv *= U_MILLIS_PER_SECOND;
112-
} else if (type == IS_LONG) {
113-
rv = U_MILLIS_PER_SECOND * (double)lv;
114-
} else {
115-
*status = U_ILLEGAL_ARGUMENT_ERROR;
116-
}
117-
break;
118-
case IS_LONG:
119-
rv = U_MILLIS_PER_SECOND * (double)Z_LVAL_P(z);
120-
break;
121-
case IS_DOUBLE:
122-
rv = U_MILLIS_PER_SECOND * Z_DVAL_P(z);
123-
break;
124-
case IS_OBJECT:
125-
if (instanceof_function(Z_OBJCE_P(z), php_date_get_date_ce() TSRMLS_CC)) {
126-
zval retval;
127-
zval *zfuncname;
128-
INIT_ZVAL(retval);
129-
MAKE_STD_ZVAL(zfuncname);
130-
ZVAL_STRING(zfuncname, "getTimestamp", 1);
131-
if (call_user_function(NULL, &(z), zfuncname, &retval, 0, NULL TSRMLS_CC)
132-
!= SUCCESS || Z_TYPE(retval) != IS_LONG) {
133-
*status = U_INTERNAL_PROGRAM_ERROR;
134-
} else {
135-
rv = U_MILLIS_PER_SECOND * (double)Z_LVAL(retval);
136-
}
137-
zval_ptr_dtor(&zfuncname);
138-
} else if (instanceof_function(Z_OBJCE_P(z), Calendar_ce_ptr TSRMLS_CC)) {
139-
Calendar_object *co = (Calendar_object *)
140-
zend_object_store_get_object(z TSRMLS_CC );
141-
if (co->ucal == NULL) {
142-
*status = U_ILLEGAL_ARGUMENT_ERROR;
143-
} else {
144-
rv = (double)co->ucal->getTime(*status);
145-
}
146-
} else {
147-
/* TODO: try with cast(), get() to obtain a number */
148-
*status = U_ILLEGAL_ARGUMENT_ERROR;
149-
}
150-
break;
151-
default:
152-
*status = U_ILLEGAL_ARGUMENT_ERROR;
153-
}
154-
155-
return rv;
156-
}
157-
15894
static HashTable *umsg_get_numeric_types(MessageFormatter_object *mfo,
15995
intl_error& err TSRMLS_DC)
16096
{
@@ -613,7 +549,7 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo,
613549
}
614550
case Formattable::kDate:
615551
{
616-
double dd = umsg_helper_zval_to_millis(*elem, &err.code TSRMLS_CC);
552+
double dd = intl_zval_to_millis(*elem, &err.code TSRMLS_CC);
617553
if (U_FAILURE(err.code)) {
618554
char *message, *key_char;
619555
int key_len;

ext/intl/tests/dateformat_format.phpt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -399,24 +399,24 @@ Formatted DateTime is : 20001230 05:04 PM
399399
Date is: stdClass::__set_state(array(
400400
))
401401
------------
402-
Error while formatting as: 'datefmt_format: object must be an instance of DateTime: U_ILLEGAL_ARGUMENT_ERROR'
402+
Error while formatting as: 'datefmt_format: could not convert input into a date: U_ILLEGAL_ARGUMENT_ERROR'
403403
------------
404404
Date is: stdClass::__set_state(array(
405405
))
406406
------------
407-
Error while formatting as: 'datefmt_format: object must be an instance of DateTime: U_ILLEGAL_ARGUMENT_ERROR'
407+
Error while formatting as: 'datefmt_format: could not convert input into a date: U_ILLEGAL_ARGUMENT_ERROR'
408408
------------
409409
Date is: stdClass::__set_state(array(
410410
))
411411
------------
412-
Error while formatting as: 'datefmt_format: object must be an instance of DateTime: U_ILLEGAL_ARGUMENT_ERROR'
412+
Error while formatting as: 'datefmt_format: could not convert input into a date: U_ILLEGAL_ARGUMENT_ERROR'
413413
------------
414414
Date is: stdClass::__set_state(array(
415415
))
416416
------------
417-
Error while formatting as: 'datefmt_format: object must be an instance of DateTime: U_ILLEGAL_ARGUMENT_ERROR'
417+
Error while formatting as: 'datefmt_format: could not convert input into a date: U_ILLEGAL_ARGUMENT_ERROR'
418418
------------
419419
Date is: stdClass::__set_state(array(
420420
))
421421
------------
422-
Error while formatting as: 'datefmt_format: object must be an instance of DateTime: U_ILLEGAL_ARGUMENT_ERROR'
422+
Error while formatting as: 'datefmt_format: could not convert input into a date: U_ILLEGAL_ARGUMENT_ERROR'

0 commit comments

Comments
 (0)