1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
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 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #define __STDC_FORMAT_MACROS
22 #include <inttypes.h>
23
24 #include "../intl_cppshims.h"
25
26 #include <unicode/locid.h>
27 #include <unicode/calendar.h>
28 #include <unicode/ustring.h>
29
30 #include "../intl_convertcpp.h"
31 #include "../common/common_date.h"
32
33 extern "C" {
34 #include "../php_intl.h"
35 #define USE_TIMEZONE_POINTER 1
36 #include "../timezone/timezone_class.h"
37 #define USE_CALENDAR_POINTER 1
38 #include "calendar_class.h"
39 #include "../intl_convert.h"
40 #include <zend_exceptions.h>
41 #include <zend_interfaces.h>
42 #include <ext/date/php_date.h>
43 }
44 #include "../common/common_enum.h"
45
46 using icu::Locale;
47
PHP_METHOD(IntlCalendar,__construct)48 U_CFUNC PHP_METHOD(IntlCalendar, __construct)
49 {
50 zend_throw_exception( NULL,
51 "An object of this type cannot be created with the new operator",
52 0 );
53 }
54
PHP_FUNCTION(intlcal_create_instance)55 U_CFUNC PHP_FUNCTION(intlcal_create_instance)
56 {
57 zval *zv_timezone = NULL;
58 const char *locale_str = NULL;
59 size_t dummy;
60 TimeZone *timeZone;
61 UErrorCode status = U_ZERO_ERROR;
62 intl_error_reset(NULL);
63
64 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|zs!",
65 &zv_timezone, &locale_str, &dummy) == FAILURE) {
66 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
67 "intlcal_create_calendar: bad arguments", 0);
68 RETURN_NULL();
69 }
70
71 timeZone = timezone_process_timezone_argument(zv_timezone, NULL,
72 "intlcal_create_instance");
73 if (timeZone == NULL) {
74 RETURN_NULL();
75 }
76
77 if (!locale_str) {
78 locale_str = intl_locale_get_default();
79 }
80
81 Calendar *cal = Calendar::createInstance(timeZone,
82 Locale::createFromName(locale_str), status);
83 if (cal == NULL) {
84 delete timeZone;
85 intl_error_set(NULL, status, "Error creating ICU Calendar object", 0);
86 RETURN_NULL();
87 }
88
89 calendar_object_create(return_value, cal);
90 }
91
92 class BugStringCharEnumeration : public StringEnumeration
93 {
94 public:
BugStringCharEnumeration(UEnumeration * _uenum)95 explicit BugStringCharEnumeration(UEnumeration* _uenum) : uenum(_uenum) {}
96
~BugStringCharEnumeration()97 ~BugStringCharEnumeration()
98 {
99 uenum_close(uenum);
100 }
101
count(UErrorCode & status) const102 int32_t count(UErrorCode& status) const {
103 return uenum_count(uenum, &status);
104 }
105
snext(UErrorCode & status)106 virtual const UnicodeString* snext(UErrorCode& status)
107 {
108 int32_t length;
109 const UChar* str = uenum_unext(uenum, &length, &status);
110 if (str == 0 || U_FAILURE(status)) {
111 return 0;
112 }
113 return &unistr.setTo(str, length);
114 }
115
next(int32_t * resultLength,UErrorCode & status)116 virtual const char* next(int32_t *resultLength, UErrorCode &status)
117 {
118 int32_t length = -1;
119 const char* str = uenum_next(uenum, &length, &status);
120 if (str == 0 || U_FAILURE(status)) {
121 return 0;
122 }
123 if (resultLength) {
124 //the bug is that uenum_next doesn't set the length
125 *resultLength = (length == -1) ? (int32_t)strlen(str) : length;
126 }
127
128 return str;
129 }
130
reset(UErrorCode & status)131 void reset(UErrorCode& status)
132 {
133 uenum_reset(uenum, &status);
134 }
135
136 virtual UClassID getDynamicClassID() const;
137
138 static UClassID U_EXPORT2 getStaticClassID();
139
140 private:
141 UEnumeration *uenum;
142 };
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(BugStringCharEnumeration)143 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(BugStringCharEnumeration)
144
145 U_CFUNC PHP_FUNCTION(intlcal_get_keyword_values_for_locale)
146 {
147 UErrorCode status = U_ZERO_ERROR;
148 char *key,
149 *locale;
150 size_t key_len,
151 locale_len;
152 zend_bool commonly_used;
153 intl_error_reset(NULL);
154
155 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssb",
156 &key, &key_len, &locale, &locale_len, &commonly_used) == FAILURE) {
157 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
158 "intlcal_get_keyword_values_for_locale: bad arguments", 0);
159 RETURN_FALSE;
160 }
161
162 //does not work; see ICU bug 9194
163 #if 0
164 StringEnumeration *se = Calendar::getKeywordValuesForLocale(key,
165 Locale::createFromName(locale), (UBool)commonly_used,
166 status);
167 if (se == NULL) {
168 intl_error_set(NULL, status, "intlcal_get_keyword_values_for_locale: "
169 "error calling underlying method", 0);
170 RETURN_FALSE;
171 }
172 #else
173 UEnumeration *uenum = ucal_getKeywordValuesForLocale(
174 key, locale, !!commonly_used, &status);
175 if (U_FAILURE(status)) {
176 uenum_close(uenum);
177 intl_error_set(NULL, status, "intlcal_get_keyword_values_for_locale: "
178 "error calling underlying method", 0);
179 RETURN_FALSE;
180 }
181
182 StringEnumeration *se = new BugStringCharEnumeration(uenum);
183 #endif
184
185 IntlIterator_from_StringEnumeration(se, return_value);
186 }
187
PHP_FUNCTION(intlcal_get_now)188 U_CFUNC PHP_FUNCTION(intlcal_get_now)
189 {
190 intl_error_reset(NULL);
191
192 if (zend_parse_parameters_none() == FAILURE) {
193 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
194 "intlcal_get_now: bad arguments", 0);
195 RETURN_FALSE;
196 }
197
198 RETURN_DOUBLE((double)Calendar::getNow());
199 }
200
PHP_FUNCTION(intlcal_get_available_locales)201 U_CFUNC PHP_FUNCTION(intlcal_get_available_locales)
202 {
203 intl_error_reset(NULL);
204
205 if (zend_parse_parameters_none() == FAILURE) {
206 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
207 "intlcal_get_available_locales: bad arguments", 0);
208 RETURN_FALSE;
209 }
210
211 int32_t count;
212 const Locale *availLocales = Calendar::getAvailableLocales(count);
213 array_init(return_value);
214 for (int i = 0; i < count; i++) {
215 Locale locale = availLocales[i];
216 add_next_index_string(return_value, locale.getName());
217 }
218 }
219
_php_intlcal_field_uec_ret_in32t_method(int32_t (Calendar::* func)(UCalendarDateFields,UErrorCode &)const,const char * method_name,INTERNAL_FUNCTION_PARAMETERS)220 static void _php_intlcal_field_uec_ret_in32t_method(
221 int32_t (Calendar::*func)(UCalendarDateFields, UErrorCode&) const,
222 const char *method_name,
223 INTERNAL_FUNCTION_PARAMETERS)
224 {
225 zend_long field;
226 char *message;
227 CALENDAR_METHOD_INIT_VARS;
228
229 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
230 "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) {
231 spprintf(&message, 0, "%s: bad arguments", method_name);
232 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1);
233 efree(message);
234 RETURN_FALSE;
235 }
236
237 if (field < 0 || field >= UCAL_FIELD_COUNT) {
238 spprintf(&message, 0, "%s: invalid field", method_name);
239 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1);
240 efree(message);
241 RETURN_FALSE;
242 }
243
244 CALENDAR_METHOD_FETCH_OBJECT;
245
246 int32_t result = (co->ucal->*func)(
247 (UCalendarDateFields)field, CALENDAR_ERROR_CODE(co));
248 INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed");
249
250 RETURN_LONG((zend_long)result);
251 }
252
PHP_FUNCTION(intlcal_get)253 U_CFUNC PHP_FUNCTION(intlcal_get)
254 {
255 _php_intlcal_field_uec_ret_in32t_method(&Calendar::get,
256 "intlcal_get", INTERNAL_FUNCTION_PARAM_PASSTHRU);
257 }
258
PHP_FUNCTION(intlcal_get_time)259 U_CFUNC PHP_FUNCTION(intlcal_get_time)
260 {
261 CALENDAR_METHOD_INIT_VARS;
262
263 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
264 &object, Calendar_ce_ptr) == FAILURE) {
265 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
266 "intlcal_get_time: bad arguments", 0);
267 RETURN_FALSE;
268 }
269
270 CALENDAR_METHOD_FETCH_OBJECT;
271
272 UDate result = co->ucal->getTime(CALENDAR_ERROR_CODE(co));
273 INTL_METHOD_CHECK_STATUS(co,
274 "intlcal_get_time: error calling ICU Calendar::getTime");
275
276 RETURN_DOUBLE((double)result);
277 }
278
PHP_FUNCTION(intlcal_set_time)279 U_CFUNC PHP_FUNCTION(intlcal_set_time)
280 {
281 double time_arg;
282 CALENDAR_METHOD_INIT_VARS;
283
284 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Od",
285 &object, Calendar_ce_ptr, &time_arg) == FAILURE) {
286 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
287 "intlcal_set_time: bad arguments", 0);
288 RETURN_FALSE;
289 }
290
291 CALENDAR_METHOD_FETCH_OBJECT;
292
293 co->ucal->setTime((UDate)time_arg, CALENDAR_ERROR_CODE(co));
294 INTL_METHOD_CHECK_STATUS(co, "Call to underlying method failed");
295
296 RETURN_TRUE;
297 }
298
PHP_FUNCTION(intlcal_add)299 U_CFUNC PHP_FUNCTION(intlcal_add)
300 {
301 zend_long field,
302 amount;
303 CALENDAR_METHOD_INIT_VARS;
304
305 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
306 "Oll", &object, Calendar_ce_ptr, &field, &amount) == FAILURE) {
307 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
308 "intlcal_add: bad arguments", 0);
309 RETURN_FALSE;
310 }
311
312 if (field < 0 || field >= UCAL_FIELD_COUNT) {
313 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
314 "intlcal_add: invalid field", 0);
315 RETURN_FALSE;
316 }
317 if (amount < INT32_MIN || amount > INT32_MAX) {
318 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
319 "intlcal_add: amount out of bounds", 0);
320 RETURN_FALSE;
321 }
322
323 CALENDAR_METHOD_FETCH_OBJECT;
324
325 co->ucal->add((UCalendarDateFields)field, (int32_t)amount, CALENDAR_ERROR_CODE(co));
326 INTL_METHOD_CHECK_STATUS(co, "intlcal_add: Call to underlying method failed");
327
328 RETURN_TRUE;
329 }
330
PHP_FUNCTION(intlcal_set_time_zone)331 U_CFUNC PHP_FUNCTION(intlcal_set_time_zone)
332 {
333 zval *zv_timezone;
334 TimeZone *timeZone;
335 CALENDAR_METHOD_INIT_VARS;
336
337 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
338 "Oz!", &object, Calendar_ce_ptr, &zv_timezone) == FAILURE) {
339 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
340 "intlcal_set_time_zone: bad arguments", 0);
341 RETURN_FALSE;
342 }
343
344 CALENDAR_METHOD_FETCH_OBJECT;
345
346 if (zv_timezone == NULL) {
347 RETURN_TRUE; /* the method does nothing if passed null */
348 }
349
350 timeZone = timezone_process_timezone_argument(zv_timezone,
351 CALENDAR_ERROR_P(co), "intlcal_set_time_zone");
352 if (timeZone == NULL) {
353 RETURN_FALSE;
354 }
355
356 co->ucal->adoptTimeZone(timeZone);
357
358 RETURN_TRUE;
359 }
360
361
_php_intlcal_before_after(UBool (Calendar::* func)(const Calendar &,UErrorCode &)const,INTERNAL_FUNCTION_PARAMETERS)362 static void _php_intlcal_before_after(
363 UBool (Calendar::*func)(const Calendar&, UErrorCode&) const,
364 INTERNAL_FUNCTION_PARAMETERS)
365 {
366 zval *when_object;
367 Calendar_object *when_co;
368 CALENDAR_METHOD_INIT_VARS;
369
370 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
371 "OO", &object, Calendar_ce_ptr, &when_object, Calendar_ce_ptr)
372 == FAILURE) {
373 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
374 "intlcal_before/after: bad arguments", 0);
375 RETURN_FALSE;
376 }
377
378 CALENDAR_METHOD_FETCH_OBJECT;
379
380 when_co = Z_INTL_CALENDAR_P(when_object);
381 if (when_co->ucal == NULL) {
382 intl_errors_set(&co->err, U_ILLEGAL_ARGUMENT_ERROR,
383 "intlcal_before/after: Other IntlCalendar was unconstructed", 0);
384 RETURN_FALSE;
385 }
386
387 UBool res = (co->ucal->*func)(*when_co->ucal, CALENDAR_ERROR_CODE(co));
388 INTL_METHOD_CHECK_STATUS(co, "intlcal_before/after: Error calling ICU method");
389
390 RETURN_BOOL((int)res);
391 }
392
PHP_FUNCTION(intlcal_after)393 U_CFUNC PHP_FUNCTION(intlcal_after)
394 {
395 _php_intlcal_before_after(&Calendar::after, INTERNAL_FUNCTION_PARAM_PASSTHRU);
396 }
397
PHP_FUNCTION(intlcal_before)398 U_CFUNC PHP_FUNCTION(intlcal_before)
399 {
400 _php_intlcal_before_after(&Calendar::before, INTERNAL_FUNCTION_PARAM_PASSTHRU);
401 }
402
PHP_FUNCTION(intlcal_set)403 U_CFUNC PHP_FUNCTION(intlcal_set)
404 {
405 zend_long arg1, arg2, arg3, arg4, arg5, arg6;
406 zval args_a[7] = {0},
407 *args = args_a;
408 int i;
409 int variant; /* number of args of the set() overload */
410 CALENDAR_METHOD_INIT_VARS;
411
412 object = getThis();
413
414 /* must come before zpp because zpp would convert the args in the stack to 0 */
415 if (ZEND_NUM_ARGS() > (object ? 6 : 7) ||
416 zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
417 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
418 "intlcal_set: too many arguments", 0);
419 RETURN_FALSE;
420 }
421 if (!object) {
422 args++;
423 }
424 variant = ZEND_NUM_ARGS() - (object ? 0 : 1);
425 while (variant > 2 && Z_TYPE(args[variant - 1]) == IS_NULL) {
426 variant--;
427 }
428
429 if (variant == 4 ||
430 zend_parse_method_parameters(ZEND_NUM_ARGS(), object,
431 "Oll|llll", &object, Calendar_ce_ptr, &arg1, &arg2, &arg3, &arg4,
432 &arg5, &arg6) == FAILURE) {
433 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
434 "intlcal_set: bad arguments", 0);
435 RETURN_FALSE;
436 }
437
438 for (i = 0; i < variant; i++) {
439 if (Z_LVAL(args[i]) < INT32_MIN || Z_LVAL(args[i]) > INT32_MAX) {
440 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
441 "intlcal_set: at least one of the arguments has an absolute "
442 "value that is too large", 0);
443 RETURN_FALSE;
444 }
445 }
446
447 if (variant == 2 && (arg1 < 0 || arg1 >= UCAL_FIELD_COUNT)) {
448 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
449 "intlcal_set: invalid field", 0);
450 RETURN_FALSE;
451 }
452
453 CALENDAR_METHOD_FETCH_OBJECT;
454
455 if (variant == 2) {
456 co->ucal->set((UCalendarDateFields)arg1, (int32_t)arg2);
457 } else if (variant == 3) {
458 co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3);
459 } else if (variant == 5) {
460 co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3, (int32_t)arg4, (int32_t)arg5);
461 } else if (variant == 6) {
462 co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3, (int32_t)arg4, (int32_t)arg5, (int32_t)arg6);
463 }
464
465 RETURN_TRUE;
466 }
467
PHP_FUNCTION(intlcal_roll)468 U_CFUNC PHP_FUNCTION(intlcal_roll)
469 {
470 zend_long field,
471 value;
472 zval args_a[3] = {0},
473 *args = args_a;
474 zend_bool bool_variant_val = (zend_bool)-1;
475 CALENDAR_METHOD_INIT_VARS;
476
477 object = getThis();
478
479 if (ZEND_NUM_ARGS() > (object ? 2 :3) ||
480 zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
481 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
482 "intlcal_set: too many arguments", 0);
483 RETURN_FALSE;
484 }
485 if (!object) {
486 args++;
487 }
488 if (!Z_ISUNDEF(args[1]) && (Z_TYPE(args[1]) == IS_TRUE || Z_TYPE(args[1]) == IS_FALSE)) {
489 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), object,
490 "Olb", &object, Calendar_ce_ptr, &field, &bool_variant_val)
491 == FAILURE) {
492 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
493 "intlcal_roll: bad arguments", 0);
494 RETURN_FALSE;
495 }
496 bool_variant_val = Z_TYPE(args[1]) == IS_TRUE? 1 : 0;
497 } else if (zend_parse_method_parameters(ZEND_NUM_ARGS(), object,
498 "Oll", &object, Calendar_ce_ptr, &field, &value) == FAILURE) {
499 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
500 "intlcal_roll: bad arguments", 0);
501 RETURN_FALSE;
502 }
503
504 if (field < 0 || field >= UCAL_FIELD_COUNT) {
505 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
506 "intlcal_roll: invalid field", 0);
507 RETURN_FALSE;
508 }
509 if (bool_variant_val == (zend_bool)-1 &&
510 (value < INT32_MIN || value > INT32_MAX)) {
511 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
512 "intlcal_roll: value out of bounds", 0);
513 RETURN_FALSE;
514 }
515
516 CALENDAR_METHOD_FETCH_OBJECT;
517
518 if (bool_variant_val != (zend_bool)-1) {
519 co->ucal->roll((UCalendarDateFields)field, (UBool)bool_variant_val,
520 CALENDAR_ERROR_CODE(co));
521 } else {
522 co->ucal->roll((UCalendarDateFields)field, (int32_t)value,
523 CALENDAR_ERROR_CODE(co));
524 }
525 INTL_METHOD_CHECK_STATUS(co, "intlcal_roll: Error calling ICU Calendar::roll");
526
527 RETURN_TRUE;
528 }
529
PHP_FUNCTION(intlcal_clear)530 U_CFUNC PHP_FUNCTION(intlcal_clear)
531 {
532 zend_long field;
533 zend_bool field_is_null = 1;
534 CALENDAR_METHOD_INIT_VARS;
535
536 if (zend_parse_method_parameters(ZEND_NUM_ARGS(),
537 getThis(), "O|l!", &object, Calendar_ce_ptr, &field, &field_is_null) == FAILURE) {
538 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
539 "intlcal_clear: bad arguments", 0);
540 RETURN_FALSE;
541 }
542
543 CALENDAR_METHOD_FETCH_OBJECT;
544
545 if (field_is_null) {
546 co->ucal->clear();
547 } else {
548 if (field < 0 || field >= UCAL_FIELD_COUNT) {
549 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
550 "intlcal_clear: invalid field", 0);
551 RETURN_FALSE;
552 }
553
554 co->ucal->clear((UCalendarDateFields)field);
555 }
556
557 RETURN_TRUE;
558 }
559
PHP_FUNCTION(intlcal_field_difference)560 U_CFUNC PHP_FUNCTION(intlcal_field_difference)
561 {
562 zend_long field;
563 double when;
564 CALENDAR_METHOD_INIT_VARS;
565
566 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
567 "Odl", &object, Calendar_ce_ptr, &when, &field) == FAILURE) {
568 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
569 "intlcal_field_difference: bad arguments", 0);
570 RETURN_FALSE;
571 }
572
573 if (field < 0 || field >= UCAL_FIELD_COUNT) {
574 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
575 "intlcal_field_difference: invalid field", 0);
576 RETURN_FALSE;
577 }
578
579 CALENDAR_METHOD_FETCH_OBJECT;
580
581 int32_t result = co->ucal->fieldDifference((UDate)when,
582 (UCalendarDateFields)field, CALENDAR_ERROR_CODE(co));
583 INTL_METHOD_CHECK_STATUS(co,
584 "intlcal_field_difference: Call to ICU method has failed");
585
586 RETURN_LONG((zend_long)result);
587 }
588
PHP_FUNCTION(intlcal_get_actual_maximum)589 U_CFUNC PHP_FUNCTION(intlcal_get_actual_maximum)
590 {
591 _php_intlcal_field_uec_ret_in32t_method(&Calendar::getActualMaximum,
592 "intlcal_get_actual_maximum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
593 }
594
PHP_FUNCTION(intlcal_get_actual_minimum)595 U_CFUNC PHP_FUNCTION(intlcal_get_actual_minimum)
596 {
597 _php_intlcal_field_uec_ret_in32t_method(&Calendar::getActualMinimum,
598 "intlcal_get_actual_minimum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
599 }
600
PHP_FUNCTION(intlcal_get_day_of_week_type)601 U_CFUNC PHP_FUNCTION(intlcal_get_day_of_week_type)
602 {
603 zend_long dow;
604 CALENDAR_METHOD_INIT_VARS;
605
606 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
607 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
608 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
609 "intlcal_get_day_of_week_type: bad arguments", 0);
610 RETURN_FALSE;
611 }
612
613 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
614 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
615 "intlcal_get_day_of_week_type: invalid day of week", 0);
616 RETURN_FALSE;
617 }
618
619 CALENDAR_METHOD_FETCH_OBJECT;
620
621 int32_t result = co->ucal->getDayOfWeekType(
622 (UCalendarDaysOfWeek)dow, CALENDAR_ERROR_CODE(co));
623 INTL_METHOD_CHECK_STATUS(co,
624 "intlcal_get_day_of_week_type: Call to ICU method has failed");
625
626 RETURN_LONG((zend_long)result);
627 }
628
PHP_FUNCTION(intlcal_get_first_day_of_week)629 U_CFUNC PHP_FUNCTION(intlcal_get_first_day_of_week)
630 {
631 CALENDAR_METHOD_INIT_VARS;
632
633 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
634 "O", &object, Calendar_ce_ptr) == FAILURE) {
635 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
636 "intlcal_get_first_day_of_week: bad arguments", 0);
637 RETURN_FALSE;
638 }
639
640 CALENDAR_METHOD_FETCH_OBJECT;
641
642 int32_t result = co->ucal->getFirstDayOfWeek(CALENDAR_ERROR_CODE(co));
643 INTL_METHOD_CHECK_STATUS(co,
644 "intlcal_get_first_day_of_week: Call to ICU method has failed");
645
646 RETURN_LONG((zend_long)result);
647 }
648
_php_intlcal_field_ret_in32t_method(int32_t (Calendar::* func)(UCalendarDateFields)const,const char * method_name,INTERNAL_FUNCTION_PARAMETERS)649 static void _php_intlcal_field_ret_in32t_method(
650 int32_t (Calendar::*func)(UCalendarDateFields) const,
651 const char *method_name,
652 INTERNAL_FUNCTION_PARAMETERS)
653 {
654 zend_long field;
655 char *message;
656 CALENDAR_METHOD_INIT_VARS;
657
658 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
659 "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) {
660 spprintf(&message, 0, "%s: bad arguments", method_name);
661 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1);
662 efree(message);
663 RETURN_FALSE;
664 }
665
666 if (field < 0 || field >= UCAL_FIELD_COUNT) {
667 spprintf(&message, 0, "%s: invalid field", method_name);
668 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1);
669 efree(message);
670 RETURN_FALSE;
671 }
672
673 CALENDAR_METHOD_FETCH_OBJECT;
674
675 int32_t result = (co->ucal->*func)((UCalendarDateFields)field);
676 INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed");
677
678 RETURN_LONG((zend_long)result);
679 }
680
PHP_FUNCTION(intlcal_get_greatest_minimum)681 U_CFUNC PHP_FUNCTION(intlcal_get_greatest_minimum)
682 {
683 _php_intlcal_field_ret_in32t_method(&Calendar::getGreatestMinimum,
684 "intlcal_get_greatest_minimum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
685 }
686
PHP_FUNCTION(intlcal_get_least_maximum)687 U_CFUNC PHP_FUNCTION(intlcal_get_least_maximum)
688 {
689 _php_intlcal_field_ret_in32t_method(&Calendar::getLeastMaximum,
690 "intlcal_get_least_maximum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
691 }
692
PHP_FUNCTION(intlcal_get_locale)693 U_CFUNC PHP_FUNCTION(intlcal_get_locale)
694 {
695 zend_long locale_type;
696 CALENDAR_METHOD_INIT_VARS;
697
698 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
699 "Ol", &object, Calendar_ce_ptr, &locale_type) == FAILURE) {
700 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
701 "intlcal_get_locale: bad arguments", 0);
702 RETURN_FALSE;
703 }
704
705 if (locale_type != ULOC_ACTUAL_LOCALE && locale_type != ULOC_VALID_LOCALE) {
706 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
707 "intlcal_get_locale: invalid locale type", 0);
708 RETURN_FALSE;
709 }
710
711 CALENDAR_METHOD_FETCH_OBJECT;
712
713 Locale locale = co->ucal->getLocale((ULocDataLocaleType)locale_type,
714 CALENDAR_ERROR_CODE(co));
715 INTL_METHOD_CHECK_STATUS(co,
716 "intlcal_get_locale: Call to ICU method has failed");
717
718 RETURN_STRING(locale.getName());
719 }
720
PHP_FUNCTION(intlcal_get_maximum)721 U_CFUNC PHP_FUNCTION(intlcal_get_maximum)
722 {
723 _php_intlcal_field_ret_in32t_method(&Calendar::getMaximum,
724 "intlcal_get_maximum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
725 }
726
PHP_FUNCTION(intlcal_get_minimal_days_in_first_week)727 U_CFUNC PHP_FUNCTION(intlcal_get_minimal_days_in_first_week)
728 {
729 CALENDAR_METHOD_INIT_VARS;
730
731 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
732 "O", &object, Calendar_ce_ptr) == FAILURE) {
733 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
734 "intlcal_get_minimal_days_in_first_week: bad arguments", 0);
735 RETURN_FALSE;
736 }
737
738 CALENDAR_METHOD_FETCH_OBJECT;
739
740 uint8_t result = co->ucal->getMinimalDaysInFirstWeek();
741 INTL_METHOD_CHECK_STATUS(co,
742 "intlcal_get_first_day_of_week: Call to ICU method has failed");
743
744 RETURN_LONG((zend_long)result);
745 }
746
PHP_FUNCTION(intlcal_get_minimum)747 U_CFUNC PHP_FUNCTION(intlcal_get_minimum)
748 {
749 _php_intlcal_field_ret_in32t_method(&Calendar::getMinimum,
750 "intlcal_get_minimum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
751 }
752
PHP_FUNCTION(intlcal_get_time_zone)753 U_CFUNC PHP_FUNCTION(intlcal_get_time_zone)
754 {
755 CALENDAR_METHOD_INIT_VARS;
756
757 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
758 "O", &object, Calendar_ce_ptr) == FAILURE) {
759 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
760 "intlcal_get_time_zone: bad arguments", 0);
761 RETURN_FALSE;
762 }
763
764 CALENDAR_METHOD_FETCH_OBJECT;
765
766 TimeZone *tz = co->ucal->getTimeZone().clone();
767 if (tz == NULL) {
768 intl_errors_set(CALENDAR_ERROR_P(co), U_MEMORY_ALLOCATION_ERROR,
769 "intlcal_get_time_zone: could not clone TimeZone", 0);
770 RETURN_FALSE;
771 }
772
773 timezone_object_construct(tz, return_value, 1);
774 }
775
PHP_FUNCTION(intlcal_get_type)776 U_CFUNC PHP_FUNCTION(intlcal_get_type)
777 {
778 CALENDAR_METHOD_INIT_VARS;
779
780 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
781 "O", &object, Calendar_ce_ptr) == FAILURE) {
782 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
783 "intlcal_get_type: bad arguments", 0);
784 RETURN_FALSE;
785 }
786
787 CALENDAR_METHOD_FETCH_OBJECT;
788
789 RETURN_STRING(co->ucal->getType());
790 }
791
PHP_FUNCTION(intlcal_get_weekend_transition)792 U_CFUNC PHP_FUNCTION(intlcal_get_weekend_transition)
793 {
794 zend_long dow;
795 CALENDAR_METHOD_INIT_VARS;
796
797 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
798 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
799 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
800 "intlcal_get_weekend_transition: bad arguments", 0);
801 RETURN_FALSE;
802 }
803
804 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
805 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
806 "intlcal_get_weekend_transition: invalid day of week", 0);
807 RETURN_FALSE;
808 }
809
810 CALENDAR_METHOD_FETCH_OBJECT;
811
812 int32_t res = co->ucal->getWeekendTransition((UCalendarDaysOfWeek)dow,
813 CALENDAR_ERROR_CODE(co));
814 INTL_METHOD_CHECK_STATUS(co, "intlcal_get_weekend_transition: "
815 "Error calling ICU method");
816
817 RETURN_LONG((zend_long)res);
818 }
819
PHP_FUNCTION(intlcal_in_daylight_time)820 U_CFUNC PHP_FUNCTION(intlcal_in_daylight_time)
821 {
822 CALENDAR_METHOD_INIT_VARS;
823
824 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
825 "O", &object, Calendar_ce_ptr) == FAILURE) {
826 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
827 "intlcal_in_daylight_time: bad arguments", 0);
828 RETURN_FALSE;
829 }
830
831 CALENDAR_METHOD_FETCH_OBJECT;
832
833 UBool ret = co->ucal->inDaylightTime(CALENDAR_ERROR_CODE(co));
834 INTL_METHOD_CHECK_STATUS(co, "intlcal_in_daylight_time: "
835 "Error calling ICU method");
836
837 RETURN_BOOL((int)ret);
838 }
839
PHP_FUNCTION(intlcal_is_equivalent_to)840 U_CFUNC PHP_FUNCTION(intlcal_is_equivalent_to)
841 {
842 zval *other_object;
843 Calendar_object *other_co;
844 CALENDAR_METHOD_INIT_VARS;
845
846 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
847 "OO", &object, Calendar_ce_ptr, &other_object, Calendar_ce_ptr)
848 == FAILURE) {
849 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
850 "intlcal_is_equivalent_to: bad arguments", 0);
851 RETURN_FALSE;
852 }
853
854 other_co = Z_INTL_CALENDAR_P(other_object);
855 if (other_co->ucal == NULL) {
856 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intlcal_is_equivalent_to:"
857 " Other IntlCalendar is unconstructed", 0);
858 RETURN_FALSE;
859 }
860
861 CALENDAR_METHOD_FETCH_OBJECT;
862
863 RETURN_BOOL((int)co->ucal->isEquivalentTo(*other_co->ucal));
864 }
865
PHP_FUNCTION(intlcal_is_lenient)866 U_CFUNC PHP_FUNCTION(intlcal_is_lenient)
867 {
868 CALENDAR_METHOD_INIT_VARS;
869
870 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
871 "O", &object, Calendar_ce_ptr) == FAILURE) {
872 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
873 "intlcal_is_lenient: bad arguments", 0);
874 RETURN_FALSE;
875 }
876
877 CALENDAR_METHOD_FETCH_OBJECT;
878
879 RETURN_BOOL((int)co->ucal->isLenient());
880 }
881
PHP_FUNCTION(intlcal_is_set)882 U_CFUNC PHP_FUNCTION(intlcal_is_set)
883 {
884 zend_long field;
885 CALENDAR_METHOD_INIT_VARS;
886
887 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
888 "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) {
889 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
890 "intlcal_is_set: bad arguments", 0);
891 RETURN_FALSE;
892 }
893
894 if (field < 0 || field >= UCAL_FIELD_COUNT) {
895 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
896 "intlcal_is_set: invalid field", 0);
897 RETURN_FALSE;
898 }
899
900 CALENDAR_METHOD_FETCH_OBJECT;
901
902 RETURN_BOOL((int)co->ucal->isSet((UCalendarDateFields)field));
903 }
904
PHP_FUNCTION(intlcal_is_weekend)905 U_CFUNC PHP_FUNCTION(intlcal_is_weekend)
906 {
907 double date;
908 zend_bool date_is_null = 1;
909 CALENDAR_METHOD_INIT_VARS;
910
911 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
912 "O|d!", &object, Calendar_ce_ptr, &date, &date_is_null) == FAILURE) {
913 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
914 "intlcal_is_weekend: bad arguments", 0);
915 RETURN_FALSE;
916 }
917
918 CALENDAR_METHOD_FETCH_OBJECT;
919
920 if (date_is_null) {
921 RETURN_BOOL((int)co->ucal->isWeekend());
922 } else {
923 UBool ret = co->ucal->isWeekend((UDate)date, CALENDAR_ERROR_CODE(co));
924 INTL_METHOD_CHECK_STATUS(co, "intlcal_is_weekend: "
925 "Error calling ICU method");
926 RETURN_BOOL((int)ret);
927 }
928 }
929
930
PHP_FUNCTION(intlcal_set_first_day_of_week)931 U_CFUNC PHP_FUNCTION(intlcal_set_first_day_of_week)
932 {
933 zend_long dow;
934 CALENDAR_METHOD_INIT_VARS;
935
936 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
937 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
938 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
939 "intlcal_set_first_day_of_week: bad arguments", 0);
940 RETURN_FALSE;
941 }
942
943 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
944 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
945 "intlcal_set_first_day_of_week: invalid day of week", 0);
946 RETURN_FALSE;
947 }
948
949 CALENDAR_METHOD_FETCH_OBJECT;
950
951 co->ucal->setFirstDayOfWeek((UCalendarDaysOfWeek)dow);
952
953 RETURN_TRUE;
954 }
955
PHP_FUNCTION(intlcal_set_lenient)956 U_CFUNC PHP_FUNCTION(intlcal_set_lenient)
957 {
958 zend_bool is_lenient;
959 CALENDAR_METHOD_INIT_VARS;
960
961 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
962 "Ob", &object, Calendar_ce_ptr, &is_lenient) == FAILURE) {
963 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
964 "intlcal_set_lenient: bad arguments", 0);
965 RETURN_FALSE;
966 }
967
968 CALENDAR_METHOD_FETCH_OBJECT;
969
970 co->ucal->setLenient((UBool) is_lenient);
971
972 RETURN_TRUE;
973 }
974
PHP_FUNCTION(intlcal_set_minimal_days_in_first_week)975 U_CFUNC PHP_FUNCTION(intlcal_set_minimal_days_in_first_week)
976 {
977 zend_long num_days;
978 CALENDAR_METHOD_INIT_VARS;
979
980 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
981 "Ol", &object, Calendar_ce_ptr, &num_days) == FAILURE) {
982 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
983 "intlcal_set_minimal_days_in_first_week: bad arguments", 0);
984 RETURN_FALSE;
985 }
986
987 if (num_days < 1 || num_days > 7) {
988 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
989 "intlcal_set_minimal_days_in_first_week: invalid number of days; "
990 "must be between 1 and 7", 0);
991 RETURN_FALSE;
992 }
993
994 CALENDAR_METHOD_FETCH_OBJECT;
995
996 co->ucal->setMinimalDaysInFirstWeek((uint8_t)num_days);
997
998 RETURN_TRUE;
999 }
1000
PHP_FUNCTION(intlcal_equals)1001 U_CFUNC PHP_FUNCTION(intlcal_equals)
1002 {
1003 zval *other_object;
1004 Calendar_object *other_co;
1005 CALENDAR_METHOD_INIT_VARS;
1006
1007 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1008 "OO", &object, Calendar_ce_ptr, &other_object, Calendar_ce_ptr)
1009 == FAILURE) {
1010 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1011 "intlcal_equals: bad arguments", 0);
1012 RETURN_FALSE;
1013 }
1014
1015 CALENDAR_METHOD_FETCH_OBJECT;
1016 other_co = Z_INTL_CALENDAR_P(other_object);
1017 if (other_co->ucal == NULL) {
1018 intl_errors_set(&co->err, U_ILLEGAL_ARGUMENT_ERROR,
1019 "intlcal_equals: The second IntlCalendar is unconstructed", 0);
1020 RETURN_FALSE;
1021 }
1022
1023 UBool result = co->ucal->equals(*other_co->ucal, CALENDAR_ERROR_CODE(co));
1024 INTL_METHOD_CHECK_STATUS(co, "intlcal_equals: error calling ICU Calendar::equals");
1025
1026 RETURN_BOOL((int)result);
1027 }
1028
PHP_FUNCTION(intlcal_get_repeated_wall_time_option)1029 U_CFUNC PHP_FUNCTION(intlcal_get_repeated_wall_time_option)
1030 {
1031 CALENDAR_METHOD_INIT_VARS;
1032
1033 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1034 "O", &object, Calendar_ce_ptr) == FAILURE) {
1035 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1036 "intlcal_get_repeated_wall_time_option: bad arguments", 0);
1037 RETURN_FALSE;
1038 }
1039
1040 CALENDAR_METHOD_FETCH_OBJECT;
1041
1042 RETURN_LONG(co->ucal->getRepeatedWallTimeOption());
1043 }
1044
PHP_FUNCTION(intlcal_get_skipped_wall_time_option)1045 U_CFUNC PHP_FUNCTION(intlcal_get_skipped_wall_time_option)
1046 {
1047 CALENDAR_METHOD_INIT_VARS;
1048
1049 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1050 "O", &object, Calendar_ce_ptr) == FAILURE) {
1051 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1052 "intlcal_get_skipped_wall_time_option: bad arguments", 0);
1053 RETURN_FALSE;
1054 }
1055
1056 CALENDAR_METHOD_FETCH_OBJECT;
1057
1058 RETURN_LONG(co->ucal->getSkippedWallTimeOption());
1059 }
1060
PHP_FUNCTION(intlcal_set_repeated_wall_time_option)1061 U_CFUNC PHP_FUNCTION(intlcal_set_repeated_wall_time_option)
1062 {
1063 zend_long option;
1064 CALENDAR_METHOD_INIT_VARS;
1065
1066 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1067 "Ol", &object, Calendar_ce_ptr, &option) == FAILURE) {
1068 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1069 "intlcal_set_repeated_wall_time_option: bad arguments", 0);
1070 RETURN_FALSE;
1071 }
1072
1073 if (option != UCAL_WALLTIME_FIRST && option != UCAL_WALLTIME_LAST) {
1074 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1075 "intlcal_set_repeated_wall_time_option: invalid option", 0);
1076 RETURN_FALSE;
1077 }
1078
1079 CALENDAR_METHOD_FETCH_OBJECT;
1080
1081 co->ucal->setRepeatedWallTimeOption((UCalendarWallTimeOption)option);
1082
1083 RETURN_TRUE;
1084 }
1085
PHP_FUNCTION(intlcal_set_skipped_wall_time_option)1086 U_CFUNC PHP_FUNCTION(intlcal_set_skipped_wall_time_option)
1087 {
1088 zend_long option;
1089 CALENDAR_METHOD_INIT_VARS;
1090
1091 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1092 "Ol", &object, Calendar_ce_ptr, &option) == FAILURE) {
1093 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1094 "intlcal_set_skipped_wall_time_option: bad arguments", 0);
1095 RETURN_FALSE;
1096 }
1097
1098 if (option != UCAL_WALLTIME_FIRST && option != UCAL_WALLTIME_LAST
1099 && option != UCAL_WALLTIME_NEXT_VALID) {
1100 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1101 "intlcal_set_skipped_wall_time_option: invalid option", 0);
1102 RETURN_FALSE;
1103 }
1104
1105 CALENDAR_METHOD_FETCH_OBJECT;
1106
1107 co->ucal->setSkippedWallTimeOption((UCalendarWallTimeOption)option);
1108
1109 RETURN_TRUE;
1110 }
1111
PHP_FUNCTION(intlcal_from_date_time)1112 U_CFUNC PHP_FUNCTION(intlcal_from_date_time)
1113 {
1114 zval *zv_arg,
1115 zv_tmp,
1116 *zv_datetime = NULL,
1117 zv_timestamp;
1118 php_date_obj *datetime;
1119 char *locale_str = NULL;
1120 size_t locale_str_len;
1121 TimeZone *timeZone;
1122 UErrorCode status = U_ZERO_ERROR;
1123 Calendar *cal;
1124 intl_error_reset(NULL);
1125
1126 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|s!",
1127 &zv_arg, &locale_str, &locale_str_len) == FAILURE) {
1128 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1129 "intlcal_from_date_time: bad arguments", 0);
1130 RETURN_NULL();
1131 }
1132
1133 if (!(Z_TYPE_P(zv_arg) == IS_OBJECT && instanceof_function(
1134 Z_OBJCE_P(zv_arg), php_date_get_date_ce()))) {
1135 object_init_ex(&zv_tmp, php_date_get_date_ce());
1136 zend_call_method_with_1_params(&zv_tmp, NULL, &Z_OBJCE(zv_tmp)->constructor, "__construct", NULL, zv_arg);
1137 zv_datetime = &zv_tmp;
1138 if (EG(exception)) {
1139 zend_object_store_ctor_failed(Z_OBJ(zv_tmp));
1140 goto error;
1141 }
1142 } else {
1143 zv_datetime = zv_arg;
1144 }
1145
1146 datetime = Z_PHPDATE_P(zv_datetime);
1147 if (!datetime->time) {
1148 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1149 "intlcal_from_date_time: DateTime object is unconstructed",
1150 0);
1151 goto error;
1152 }
1153
1154 zend_call_method_with_0_params(zv_datetime, php_date_get_date_ce(), NULL, "gettimestamp", &zv_timestamp);
1155 if (Z_TYPE(zv_timestamp) != IS_LONG) {
1156 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1157 "intlcal_from_date_time: bad DateTime; call to "
1158 "DateTime::getTimestamp() failed", 0);
1159 zval_ptr_dtor(&zv_timestamp);
1160 goto error;
1161 }
1162
1163 if (!datetime->time->is_localtime) {
1164 timeZone = TimeZone::getGMT()->clone();
1165 } else {
1166 timeZone = timezone_convert_datetimezone(datetime->time->zone_type,
1167 datetime, 1, NULL, "intlcal_from_date_time");
1168 if (timeZone == NULL) {
1169 goto error;
1170 }
1171 }
1172
1173 if (!locale_str) {
1174 locale_str = const_cast<char*>(intl_locale_get_default());
1175 }
1176
1177 cal = Calendar::createInstance(timeZone,
1178 Locale::createFromName(locale_str), status);
1179 if (cal == NULL) {
1180 delete timeZone;
1181 intl_error_set(NULL, status, "intlcal_from_date_time: "
1182 "error creating ICU Calendar object", 0);
1183 goto error;
1184 }
1185 cal->setTime(((UDate)Z_LVAL(zv_timestamp)) * 1000., status);
1186 if (U_FAILURE(status)) {
1187 /* time zone was adopted by cal; should not be deleted here */
1188 delete cal;
1189 intl_error_set(NULL, status, "intlcal_from_date_time: "
1190 "error creating ICU Calendar::setTime()", 0);
1191 goto error;
1192 }
1193
1194 calendar_object_create(return_value, cal);
1195
1196 error:
1197 if (zv_datetime && zv_datetime != zv_arg) {
1198 zval_ptr_dtor(zv_datetime);
1199 }
1200 }
1201
PHP_FUNCTION(intlcal_to_date_time)1202 U_CFUNC PHP_FUNCTION(intlcal_to_date_time)
1203 {
1204 zval retval;
1205 CALENDAR_METHOD_INIT_VARS;
1206
1207 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
1208 &object, Calendar_ce_ptr) == FAILURE) {
1209 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1210 "intlcal_to_date_time: bad arguments", 0);
1211 RETURN_FALSE;
1212 }
1213
1214 CALENDAR_METHOD_FETCH_OBJECT;
1215
1216 /* There are no exported functions in ext/date to this
1217 * in a more native fashion */
1218 double date = co->ucal->getTime(CALENDAR_ERROR_CODE(co)) / 1000.;
1219 int64_t ts;
1220 char ts_str[sizeof("@-9223372036854775808")];
1221 int ts_str_len;
1222 zval ts_zval, tmp;
1223
1224 INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed");
1225
1226 if (date > (double)U_INT64_MAX || date < (double)U_INT64_MIN) {
1227 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1228 "intlcal_to_date_time: The calendar date is out of the "
1229 "range for a 64-bit integer", 0);
1230 RETURN_FALSE;
1231 }
1232
1233 ZVAL_UNDEF(&retval);
1234 ts = (int64_t)date;
1235
1236 ts_str_len = slprintf(ts_str, sizeof(ts_str), "@%" PRIi64, ts);
1237 ZVAL_STRINGL(&ts_zval, ts_str, ts_str_len);
1238
1239 /* Now get the time zone */
1240 const TimeZone& tz = co->ucal->getTimeZone();
1241 zval *timezone_zval = timezone_convert_to_datetimezone(
1242 &tz, CALENDAR_ERROR_P(co), "intlcal_to_date_time", &tmp);
1243 if (timezone_zval == NULL) {
1244 zval_ptr_dtor(&ts_zval);
1245 RETURN_FALSE;
1246 }
1247
1248 /* resources allocated from now on */
1249
1250 /* Finally, instantiate object and call constructor */
1251 object_init_ex(return_value, php_date_get_date_ce());
1252 zend_call_method_with_2_params(return_value, NULL, &Z_OBJCE_P(return_value)->constructor, "__construct", NULL, &ts_zval, timezone_zval);
1253 if (EG(exception)) {
1254 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1255 "intlcal_to_date_time: DateTime constructor has thrown exception",
1256 1);
1257 zend_object_store_ctor_failed(Z_OBJ_P(return_value));
1258 zval_ptr_dtor(return_value);
1259 zval_ptr_dtor(&ts_zval);
1260
1261 RETVAL_FALSE;
1262 goto error;
1263 }
1264 zval_ptr_dtor(&ts_zval);
1265
1266 /* due to bug #40743, we have to set the time zone again */
1267 zend_call_method_with_1_params(return_value, NULL, NULL, "settimezone",
1268 &retval, timezone_zval);
1269 if (Z_ISUNDEF(retval) || Z_TYPE(retval) == IS_FALSE) {
1270 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1271 "intlcal_to_date_time: call to DateTime::setTimeZone has failed",
1272 1);
1273 zval_ptr_dtor(return_value);
1274 RETVAL_FALSE;
1275 goto error;
1276 }
1277
1278 error:
1279 zval_ptr_dtor(timezone_zval);
1280 zval_ptr_dtor(&retval);
1281 }
1282
PHP_FUNCTION(intlcal_get_error_code)1283 U_CFUNC PHP_FUNCTION(intlcal_get_error_code)
1284 {
1285 CALENDAR_METHOD_INIT_VARS;
1286
1287 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
1288 &object, Calendar_ce_ptr) == FAILURE) {
1289 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1290 "intlcal_get_error_code: bad arguments", 0);
1291 RETURN_FALSE;
1292 }
1293
1294 /* Fetch the object (without resetting its last error code ). */
1295 co = Z_INTL_CALENDAR_P(object);
1296 if (co == NULL)
1297 RETURN_FALSE;
1298
1299 RETURN_LONG((zend_long)CALENDAR_ERROR_CODE(co));
1300 }
1301
PHP_FUNCTION(intlcal_get_error_message)1302 U_CFUNC PHP_FUNCTION(intlcal_get_error_message)
1303 {
1304 zend_string* message = NULL;
1305 CALENDAR_METHOD_INIT_VARS;
1306
1307 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
1308 &object, Calendar_ce_ptr) == FAILURE) {
1309 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
1310 "intlcal_get_error_message: bad arguments", 0 );
1311 RETURN_FALSE;
1312 }
1313
1314
1315 /* Fetch the object (without resetting its last error code ). */
1316 co = Z_INTL_CALENDAR_P(object);
1317 if (co == NULL)
1318 RETURN_FALSE;
1319
1320 /* Return last error message. */
1321 message = intl_error_get_message(CALENDAR_ERROR_P(co));
1322 RETURN_STR(message);
1323 }
1324