@@ -39,10 +39,45 @@ using icu::Locale;
39
39
using icu::UnicodeString;
40
40
using icu::StringPiece;
41
41
42
+ #define ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE (argument, zpp_arg_position ) \
43
+ if (UNEXPECTED(argument < INT32_MIN || argument > INT32_MAX)) { \
44
+ zend_argument_value_error (zpp_arg_position, " must be between %d and %d" , INT32_MIN, INT32_MAX); \
45
+ RETURN_THROWS (); \
46
+ }
47
+
42
48
static inline GregorianCalendar *fetch_greg (Calendar_object *co) {
43
49
return (GregorianCalendar*)co->ucal ;
44
50
}
45
51
52
+ static bool set_gregorian_calendar_time_zone (GregorianCalendar *gcal, UErrorCode status)
53
+ {
54
+ if (U_FAILURE (status)) {
55
+ intl_error_set (NULL , status,
56
+ " IntlGregorianCalendar: Error creating ICU GregorianCalendar from date" ,
57
+ 0
58
+ );
59
+
60
+ return false ;
61
+ }
62
+
63
+ timelib_tzinfo *tzinfo = get_timezone_info ();
64
+ UnicodeString tzstr = UnicodeString::fromUTF8 (StringPiece (tzinfo->name ));
65
+ if (tzstr.isBogus ()) {
66
+ intl_error_set (NULL , U_ILLEGAL_ARGUMENT_ERROR,
67
+ " IntlGregorianCalendar: Could not create UTF-8 string "
68
+ " from PHP's default timezone name (see date_default_timezone_get())" ,
69
+ 0
70
+ );
71
+
72
+ return false ;
73
+ }
74
+
75
+ TimeZone *tz = TimeZone::createTimeZone (tzstr);
76
+ gcal->adoptTimeZone (tz);
77
+
78
+ return true ;
79
+ }
80
+
46
81
static void _php_intlgregcal_constructor_body (
47
82
INTERNAL_FUNCTION_PARAMETERS, bool is_constructor, zend_error_handling *error_handling, bool *error_handling_replaced)
48
83
{
@@ -135,11 +170,7 @@ static void _php_intlgregcal_constructor_body(
135
170
} else {
136
171
// From date/time (3, 5 or 6 arguments)
137
172
for (int i = 0 ; i < variant; i++) {
138
- if (UNEXPECTED (largs[i] < INT32_MIN || largs[i] > INT32_MAX)) {
139
- zend_argument_value_error (getThis () ? (i-1 ) : i,
140
- " must be between %d and %d" , INT32_MIN, INT32_MAX);
141
- RETURN_THROWS ();
142
- }
173
+ ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE (largs[i], getThis () ? (i-1 ) : i);
143
174
}
144
175
145
176
if (variant == 3 ) {
@@ -152,37 +183,18 @@ static void _php_intlgregcal_constructor_body(
152
183
gcal = new GregorianCalendar ((int32_t )largs[0 ], (int32_t )largs[1 ],
153
184
(int32_t )largs[2 ], (int32_t )largs[3 ], (int32_t )largs[4 ], (int32_t )largs[5 ],
154
185
status);
155
- }
156
- if (U_FAILURE (status)) {
157
- intl_error_set (NULL , status, " intlgregcal_create_instance: error "
158
- " creating ICU GregorianCalendar from date" , 0 );
159
- if (gcal) {
160
- delete gcal;
161
- }
162
- if (!is_constructor) {
163
- zval_ptr_dtor (return_value);
164
- RETVAL_NULL ();
165
- }
166
- return ;
186
+ } else {
187
+ ZEND_UNREACHABLE ();
167
188
}
168
189
169
- timelib_tzinfo *tzinfo = get_timezone_info ();
170
- UnicodeString tzstr = UnicodeString::fromUTF8 (StringPiece (tzinfo->name ));
171
- if (tzstr.isBogus ()) {
172
- intl_error_set (NULL , U_ILLEGAL_ARGUMENT_ERROR,
173
- " intlgregcal_create_instance: could not create UTF-8 string "
174
- " from PHP's default timezone name (see date_default_timezone_get())" ,
175
- 0 );
190
+ if (!set_gregorian_calendar_time_zone (gcal, status)) {
176
191
delete gcal;
177
192
if (!is_constructor) {
178
193
zval_ptr_dtor (return_value);
179
194
RETVAL_NULL ();
180
195
}
181
196
return ;
182
197
}
183
-
184
- TimeZone *tz = TimeZone::createTimeZone (tzstr);
185
- gcal->adoptTimeZone (tz);
186
198
}
187
199
188
200
co->ucal = gcal;
@@ -208,6 +220,82 @@ U_CFUNC PHP_METHOD(IntlGregorianCalendar, __construct)
208
220
}
209
221
}
210
222
223
+ U_CFUNC PHP_METHOD (IntlGregorianCalendar, createFromDate)
224
+ {
225
+ zend_long year, month, day;
226
+ UErrorCode status = U_ZERO_ERROR;
227
+ zend_error_handling error_handling;
228
+ Calendar_object *co;
229
+ GregorianCalendar *gcal;
230
+
231
+ intl_error_reset (NULL );
232
+
233
+ if (zend_parse_parameters (ZEND_NUM_ARGS (), " lll" , &year, &month, &day) == FAILURE) {
234
+ RETURN_THROWS ();
235
+ }
236
+
237
+ ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE (year, 1 );
238
+ ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE (month, 2 );
239
+ ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE (day, 3 );
240
+
241
+ zend_replace_error_handling (EH_THROW, IntlException_ce_ptr, &error_handling);
242
+
243
+ gcal = new GregorianCalendar ((int32_t ) year, (int32_t ) month, (int32_t ) day, status);
244
+ if (!set_gregorian_calendar_time_zone (gcal, status)) {
245
+ delete gcal;
246
+ goto cleanup;
247
+ }
248
+
249
+ object_init_ex (return_value, GregorianCalendar_ce_ptr);
250
+ co = Z_INTL_CALENDAR_P (return_value);
251
+ co->ucal = gcal;
252
+
253
+ cleanup:
254
+ zend_restore_error_handling (&error_handling);
255
+ }
256
+
257
+ U_CFUNC PHP_METHOD (IntlGregorianCalendar, createFromDateTime)
258
+ {
259
+ zend_long year, month, day, hour, minute, second;
260
+ bool second_is_null = 1 ;
261
+ UErrorCode status = U_ZERO_ERROR;
262
+ zend_error_handling error_handling;
263
+ Calendar_object *co;
264
+ GregorianCalendar *gcal;
265
+
266
+ intl_error_reset (NULL );
267
+
268
+ if (zend_parse_parameters (ZEND_NUM_ARGS (), " lllll|l!" , &year, &month, &day, &hour, &minute, &second, &second_is_null) == FAILURE) {
269
+ RETURN_THROWS ();
270
+ }
271
+
272
+ ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE (year, 1 );
273
+ ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE (month, 2 );
274
+ ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE (day, 3 );
275
+ ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE (hour, 4 );
276
+ ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE (minute, 5 );
277
+
278
+ zend_replace_error_handling (EH_THROW, IntlException_ce_ptr, &error_handling);
279
+
280
+ if (second_is_null) {
281
+ gcal = new GregorianCalendar ((int32_t ) year, (int32_t ) month, (int32_t ) day, (int32_t ) hour, (int32_t ) minute, status);
282
+ } else {
283
+ ZEND_VALUE_ERROR_OUT_OF_BOUND_VALUE (second, 6 );
284
+ gcal = new GregorianCalendar ((int32_t ) year, (int32_t ) month, (int32_t ) day, (int32_t ) hour, (int32_t ) minute, (int32_t ) second, status);
285
+ }
286
+ if (!set_gregorian_calendar_time_zone (gcal, status)) {
287
+ delete gcal;
288
+ goto cleanup;
289
+ }
290
+
291
+ object_init_ex (return_value, GregorianCalendar_ce_ptr);
292
+ co = Z_INTL_CALENDAR_P (return_value);
293
+ co->ucal = gcal;
294
+
295
+ cleanup:
296
+ zend_restore_error_handling (&error_handling);
297
+ }
298
+
211
299
U_CFUNC PHP_FUNCTION (intlgregcal_set_gregorian_change)
212
300
{
213
301
double date;
0 commit comments