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 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 42
93 class BugStringCharEnumeration : public StringEnumeration
94 {
95 public:
BugStringCharEnumeration(UEnumeration * _uenum)96 explicit BugStringCharEnumeration(UEnumeration* _uenum) : uenum(_uenum) {}
97
~BugStringCharEnumeration()98 ~BugStringCharEnumeration()
99 {
100 uenum_close(uenum);
101 }
102
count(UErrorCode & status) const103 int32_t count(UErrorCode& status) const {
104 return uenum_count(uenum, &status);
105 }
106
snext(UErrorCode & status)107 virtual const UnicodeString* snext(UErrorCode& status)
108 {
109 int32_t length;
110 const UChar* str = uenum_unext(uenum, &length, &status);
111 if (str == 0 || U_FAILURE(status)) {
112 return 0;
113 }
114 return &unistr.setTo(str, length);
115 }
116
next(int32_t * resultLength,UErrorCode & status)117 virtual const char* next(int32_t *resultLength, UErrorCode &status)
118 {
119 int32_t length = -1;
120 const char* str = uenum_next(uenum, &length, &status);
121 if (str == 0 || U_FAILURE(status)) {
122 return 0;
123 }
124 if (resultLength) {
125 //the bug is that uenum_next doesn't set the length
126 *resultLength = (length == -1) ? (int32_t)strlen(str) : length;
127 }
128
129 return str;
130 }
131
reset(UErrorCode & status)132 void reset(UErrorCode& status)
133 {
134 uenum_reset(uenum, &status);
135 }
136
137 virtual UClassID getDynamicClassID() const;
138
139 static UClassID U_EXPORT2 getStaticClassID();
140
141 private:
142 UEnumeration *uenum;
143 };
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(BugStringCharEnumeration)144 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(BugStringCharEnumeration)
145
146 U_CFUNC PHP_FUNCTION(intlcal_get_keyword_values_for_locale)
147 {
148 UErrorCode status = U_ZERO_ERROR;
149 char *key,
150 *locale;
151 size_t key_len,
152 locale_len;
153 zend_bool commonly_used;
154 intl_error_reset(NULL);
155
156 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssb",
157 &key, &key_len, &locale, &locale_len, &commonly_used) == FAILURE) {
158 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
159 "intlcal_get_keyword_values_for_locale: bad arguments", 0);
160 RETURN_FALSE;
161 }
162
163 //does not work; see ICU bug 9194
164 #if 0
165 StringEnumeration *se = Calendar::getKeywordValuesForLocale(key,
166 Locale::createFromName(locale), (UBool)commonly_used,
167 status);
168 if (se == NULL) {
169 intl_error_set(NULL, status, "intlcal_get_keyword_values_for_locale: "
170 "error calling underlying method", 0);
171 RETURN_FALSE;
172 }
173 #else
174 UEnumeration *uenum = ucal_getKeywordValuesForLocale(
175 key, locale, !!commonly_used, &status);
176 if (U_FAILURE(status)) {
177 uenum_close(uenum);
178 intl_error_set(NULL, status, "intlcal_get_keyword_values_for_locale: "
179 "error calling underlying method", 0);
180 RETURN_FALSE;
181 }
182
183 StringEnumeration *se = new BugStringCharEnumeration(uenum);
184 #endif
185
186 IntlIterator_from_StringEnumeration(se, return_value);
187 }
188 #endif //ICU 4.2 only
189
PHP_FUNCTION(intlcal_get_now)190 U_CFUNC PHP_FUNCTION(intlcal_get_now)
191 {
192 intl_error_reset(NULL);
193
194 if (zend_parse_parameters_none() == FAILURE) {
195 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
196 "intlcal_get_now: bad arguments", 0);
197 RETURN_FALSE;
198 }
199
200 RETURN_DOUBLE((double)Calendar::getNow());
201 }
202
PHP_FUNCTION(intlcal_get_available_locales)203 U_CFUNC PHP_FUNCTION(intlcal_get_available_locales)
204 {
205 intl_error_reset(NULL);
206
207 if (zend_parse_parameters_none() == FAILURE) {
208 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
209 "intlcal_get_available_locales: bad arguments", 0);
210 RETURN_FALSE;
211 }
212
213 int32_t count;
214 const Locale *availLocales = Calendar::getAvailableLocales(count);
215 array_init(return_value);
216 for (int i = 0; i < count; i++) {
217 Locale locale = availLocales[i];
218 add_next_index_string(return_value, locale.getName());
219 }
220 }
221
_php_intlcal_field_uec_ret_in32t_method(int32_t (Calendar::* func)(UCalendarDateFields,UErrorCode &)const,const char * method_name,INTERNAL_FUNCTION_PARAMETERS)222 static void _php_intlcal_field_uec_ret_in32t_method(
223 int32_t (Calendar::*func)(UCalendarDateFields, UErrorCode&) const,
224 const char *method_name,
225 INTERNAL_FUNCTION_PARAMETERS)
226 {
227 zend_long field;
228 char *message;
229 CALENDAR_METHOD_INIT_VARS;
230
231 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
232 "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) {
233 spprintf(&message, 0, "%s: bad arguments", method_name);
234 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1);
235 efree(message);
236 RETURN_FALSE;
237 }
238
239 if (field < 0 || field >= UCAL_FIELD_COUNT) {
240 spprintf(&message, 0, "%s: invalid field", method_name);
241 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1);
242 efree(message);
243 RETURN_FALSE;
244 }
245
246 CALENDAR_METHOD_FETCH_OBJECT;
247
248 int32_t result = (co->ucal->*func)(
249 (UCalendarDateFields)field, CALENDAR_ERROR_CODE(co));
250 INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed");
251
252 RETURN_LONG((zend_long)result);
253 }
254
PHP_FUNCTION(intlcal_get)255 U_CFUNC PHP_FUNCTION(intlcal_get)
256 {
257 _php_intlcal_field_uec_ret_in32t_method(&Calendar::get,
258 "intlcal_get", INTERNAL_FUNCTION_PARAM_PASSTHRU);
259 }
260
PHP_FUNCTION(intlcal_get_time)261 U_CFUNC PHP_FUNCTION(intlcal_get_time)
262 {
263 CALENDAR_METHOD_INIT_VARS;
264
265 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
266 &object, Calendar_ce_ptr) == FAILURE) {
267 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
268 "intlcal_get_time: bad arguments", 0);
269 RETURN_FALSE;
270 }
271
272 CALENDAR_METHOD_FETCH_OBJECT;
273
274 UDate result = co->ucal->getTime(CALENDAR_ERROR_CODE(co));
275 INTL_METHOD_CHECK_STATUS(co,
276 "intlcal_get_time: error calling ICU Calendar::getTime");
277
278 RETURN_DOUBLE((double)result);
279 }
280
PHP_FUNCTION(intlcal_set_time)281 U_CFUNC PHP_FUNCTION(intlcal_set_time)
282 {
283 double time_arg;
284 CALENDAR_METHOD_INIT_VARS;
285
286 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Od",
287 &object, Calendar_ce_ptr, &time_arg) == FAILURE) {
288 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
289 "intlcal_set_time: bad arguments", 0);
290 RETURN_FALSE;
291 }
292
293 CALENDAR_METHOD_FETCH_OBJECT;
294
295 co->ucal->setTime((UDate)time_arg, CALENDAR_ERROR_CODE(co));
296 INTL_METHOD_CHECK_STATUS(co, "Call to underlying method failed");
297
298 RETURN_TRUE;
299 }
300
PHP_FUNCTION(intlcal_add)301 U_CFUNC PHP_FUNCTION(intlcal_add)
302 {
303 zend_long field,
304 amount;
305 CALENDAR_METHOD_INIT_VARS;
306
307 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
308 "Oll", &object, Calendar_ce_ptr, &field, &amount) == FAILURE) {
309 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
310 "intlcal_add: bad arguments", 0);
311 RETURN_FALSE;
312 }
313
314 if (field < 0 || field >= UCAL_FIELD_COUNT) {
315 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
316 "intlcal_add: invalid field", 0);
317 RETURN_FALSE;
318 }
319 if (amount < INT32_MIN || amount > INT32_MAX) {
320 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
321 "intlcal_add: amount out of bounds", 0);
322 RETURN_FALSE;
323 }
324
325 CALENDAR_METHOD_FETCH_OBJECT;
326
327 co->ucal->add((UCalendarDateFields)field, (int32_t)amount, CALENDAR_ERROR_CODE(co));
328 INTL_METHOD_CHECK_STATUS(co, "intlcal_add: Call to underlying method failed");
329
330 RETURN_TRUE;
331 }
332
PHP_FUNCTION(intlcal_set_time_zone)333 U_CFUNC PHP_FUNCTION(intlcal_set_time_zone)
334 {
335 zval *zv_timezone;
336 TimeZone *timeZone;
337 CALENDAR_METHOD_INIT_VARS;
338
339 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
340 "Oz!", &object, Calendar_ce_ptr, &zv_timezone) == FAILURE) {
341 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
342 "intlcal_set_time_zone: bad arguments", 0);
343 RETURN_FALSE;
344 }
345
346 CALENDAR_METHOD_FETCH_OBJECT;
347
348 if (zv_timezone == NULL) {
349 RETURN_TRUE; /* the method does nothing if passed null */
350 }
351
352 timeZone = timezone_process_timezone_argument(zv_timezone,
353 CALENDAR_ERROR_P(co), "intlcal_set_time_zone");
354 if (timeZone == NULL) {
355 RETURN_FALSE;
356 }
357
358 co->ucal->adoptTimeZone(timeZone);
359
360 RETURN_TRUE;
361 }
362
363
_php_intlcal_before_after(UBool (Calendar::* func)(const Calendar &,UErrorCode &)const,INTERNAL_FUNCTION_PARAMETERS)364 static void _php_intlcal_before_after(
365 UBool (Calendar::*func)(const Calendar&, UErrorCode&) const,
366 INTERNAL_FUNCTION_PARAMETERS)
367 {
368 zval *when_object;
369 Calendar_object *when_co;
370 CALENDAR_METHOD_INIT_VARS;
371
372 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
373 "OO", &object, Calendar_ce_ptr, &when_object, Calendar_ce_ptr)
374 == FAILURE) {
375 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
376 "intlcal_before/after: bad arguments", 0);
377 RETURN_FALSE;
378 }
379
380 CALENDAR_METHOD_FETCH_OBJECT;
381
382 when_co = Z_INTL_CALENDAR_P(when_object);
383 if (when_co->ucal == NULL) {
384 intl_errors_set(&co->err, U_ILLEGAL_ARGUMENT_ERROR,
385 "intlcal_before/after: Other IntlCalendar was unconstructed", 0);
386 RETURN_FALSE;
387 }
388
389 UBool res = (co->ucal->*func)(*when_co->ucal, CALENDAR_ERROR_CODE(co));
390 INTL_METHOD_CHECK_STATUS(co, "intlcal_before/after: Error calling ICU method");
391
392 RETURN_BOOL((int)res);
393 }
394
PHP_FUNCTION(intlcal_after)395 U_CFUNC PHP_FUNCTION(intlcal_after)
396 {
397 _php_intlcal_before_after(&Calendar::after, INTERNAL_FUNCTION_PARAM_PASSTHRU);
398 }
399
PHP_FUNCTION(intlcal_before)400 U_CFUNC PHP_FUNCTION(intlcal_before)
401 {
402 _php_intlcal_before_after(&Calendar::before, INTERNAL_FUNCTION_PARAM_PASSTHRU);
403 }
404
PHP_FUNCTION(intlcal_set)405 U_CFUNC PHP_FUNCTION(intlcal_set)
406 {
407 zend_long arg1, arg2, arg3, arg4, arg5, arg6;
408 zval args_a[7] = {0},
409 *args = args_a;
410 int i;
411 int variant; /* number of args of the set() overload */
412 CALENDAR_METHOD_INIT_VARS;
413
414 /* must come before zpp because zpp would convert the args in the stack to 0 */
415 if (ZEND_NUM_ARGS() > (getThis() ? 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 (!getThis()) {
422 args++;
423 }
424 variant = ZEND_NUM_ARGS() - (getThis() ? 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(), getThis(),
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 if (ZEND_NUM_ARGS() > (getThis() ? 2 :3) ||
478 zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
479 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
480 "intlcal_set: too many arguments", 0);
481 RETURN_FALSE;
482 }
483 if (!getThis()) {
484 args++;
485 }
486 if (!Z_ISUNDEF(args[1]) && (Z_TYPE(args[1]) == IS_TRUE || Z_TYPE(args[1]) == IS_FALSE)) {
487 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
488 "Olb", &object, Calendar_ce_ptr, &field, &bool_variant_val)
489 == FAILURE) {
490 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
491 "intlcal_roll: bad arguments", 0);
492 RETURN_FALSE;
493 }
494 bool_variant_val = Z_TYPE(args[1]) == IS_TRUE? 1 : 0;
495 } else if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
496 "Oll", &object, Calendar_ce_ptr, &field, &value) == FAILURE) {
497 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
498 "intlcal_roll: bad arguments", 0);
499 RETURN_FALSE;
500 }
501
502 if (field < 0 || field >= UCAL_FIELD_COUNT) {
503 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
504 "intlcal_roll: invalid field", 0);
505 RETURN_FALSE;
506 }
507 if (bool_variant_val == (zend_bool)-1 &&
508 (value < INT32_MIN || value > INT32_MAX)) {
509 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
510 "intlcal_roll: value out of bounds", 0);
511 RETURN_FALSE;
512 }
513
514 CALENDAR_METHOD_FETCH_OBJECT;
515
516 if (bool_variant_val != (zend_bool)-1) {
517 co->ucal->roll((UCalendarDateFields)field, (UBool)bool_variant_val,
518 CALENDAR_ERROR_CODE(co));
519 } else {
520 co->ucal->roll((UCalendarDateFields)field, (int32_t)value,
521 CALENDAR_ERROR_CODE(co));
522 }
523 INTL_METHOD_CHECK_STATUS(co, "intlcal_roll: Error calling ICU Calendar::roll");
524
525 RETURN_TRUE;
526 }
527
PHP_FUNCTION(intlcal_clear)528 U_CFUNC PHP_FUNCTION(intlcal_clear)
529 {
530 zend_long field;
531 zend_bool field_is_null = 1;
532 CALENDAR_METHOD_INIT_VARS;
533
534 if (zend_parse_method_parameters(ZEND_NUM_ARGS(),
535 getThis(), "O|l!", &object, Calendar_ce_ptr, &field, &field_is_null) == FAILURE) {
536 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
537 "intlcal_clear: bad arguments", 0);
538 RETURN_FALSE;
539 }
540
541 CALENDAR_METHOD_FETCH_OBJECT;
542
543 if (field_is_null) {
544 co->ucal->clear();
545 } else {
546 if (field < 0 || field >= UCAL_FIELD_COUNT) {
547 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
548 "intlcal_clear: invalid field", 0);
549 RETURN_FALSE;
550 }
551
552 co->ucal->clear((UCalendarDateFields)field);
553 }
554
555 RETURN_TRUE;
556 }
557
PHP_FUNCTION(intlcal_field_difference)558 U_CFUNC PHP_FUNCTION(intlcal_field_difference)
559 {
560 zend_long field;
561 double when;
562 CALENDAR_METHOD_INIT_VARS;
563
564 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
565 "Odl", &object, Calendar_ce_ptr, &when, &field) == FAILURE) {
566 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
567 "intlcal_field_difference: bad arguments", 0);
568 RETURN_FALSE;
569 }
570
571 if (field < 0 || field >= UCAL_FIELD_COUNT) {
572 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
573 "intlcal_field_difference: invalid field", 0);
574 RETURN_FALSE;
575 }
576
577 CALENDAR_METHOD_FETCH_OBJECT;
578
579 int32_t result = co->ucal->fieldDifference((UDate)when,
580 (UCalendarDateFields)field, CALENDAR_ERROR_CODE(co));
581 INTL_METHOD_CHECK_STATUS(co,
582 "intlcal_field_difference: Call to ICU method has failed");
583
584 RETURN_LONG((zend_long)result);
585 }
586
PHP_FUNCTION(intlcal_get_actual_maximum)587 U_CFUNC PHP_FUNCTION(intlcal_get_actual_maximum)
588 {
589 _php_intlcal_field_uec_ret_in32t_method(&Calendar::getActualMaximum,
590 "intlcal_get_actual_maximum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
591 }
592
PHP_FUNCTION(intlcal_get_actual_minimum)593 U_CFUNC PHP_FUNCTION(intlcal_get_actual_minimum)
594 {
595 _php_intlcal_field_uec_ret_in32t_method(&Calendar::getActualMinimum,
596 "intlcal_get_actual_minimum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
597 }
598
599 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 44
PHP_FUNCTION(intlcal_get_day_of_week_type)600 U_CFUNC PHP_FUNCTION(intlcal_get_day_of_week_type)
601 {
602 zend_long dow;
603 CALENDAR_METHOD_INIT_VARS;
604
605 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
606 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
607 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
608 "intlcal_get_day_of_week_type: bad arguments", 0);
609 RETURN_FALSE;
610 }
611
612 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
613 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
614 "intlcal_get_day_of_week_type: invalid day of week", 0);
615 RETURN_FALSE;
616 }
617
618 CALENDAR_METHOD_FETCH_OBJECT;
619
620 int32_t result = co->ucal->getDayOfWeekType(
621 (UCalendarDaysOfWeek)dow, CALENDAR_ERROR_CODE(co));
622 INTL_METHOD_CHECK_STATUS(co,
623 "intlcal_get_day_of_week_type: Call to ICU method has failed");
624
625 RETURN_LONG((zend_long)result);
626 }
627 #endif
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
792 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 44
PHP_FUNCTION(intlcal_get_weekend_transition)793 U_CFUNC PHP_FUNCTION(intlcal_get_weekend_transition)
794 {
795 zend_long dow;
796 CALENDAR_METHOD_INIT_VARS;
797
798 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
799 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
800 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
801 "intlcal_get_weekend_transition: bad arguments", 0);
802 RETURN_FALSE;
803 }
804
805 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
806 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
807 "intlcal_get_weekend_transition: invalid day of week", 0);
808 RETURN_FALSE;
809 }
810
811 CALENDAR_METHOD_FETCH_OBJECT;
812
813 int32_t res = co->ucal->getWeekendTransition((UCalendarDaysOfWeek)dow,
814 CALENDAR_ERROR_CODE(co));
815 INTL_METHOD_CHECK_STATUS(co, "intlcal_get_weekend_transition: "
816 "Error calling ICU method");
817
818 RETURN_LONG((zend_long)res);
819 }
820 #endif
821
PHP_FUNCTION(intlcal_in_daylight_time)822 U_CFUNC PHP_FUNCTION(intlcal_in_daylight_time)
823 {
824 CALENDAR_METHOD_INIT_VARS;
825
826 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
827 "O", &object, Calendar_ce_ptr) == FAILURE) {
828 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
829 "intlcal_in_daylight_time: bad arguments", 0);
830 RETURN_FALSE;
831 }
832
833 CALENDAR_METHOD_FETCH_OBJECT;
834
835 UBool ret = co->ucal->inDaylightTime(CALENDAR_ERROR_CODE(co));
836 INTL_METHOD_CHECK_STATUS(co, "intlcal_in_daylight_time: "
837 "Error calling ICU method");
838
839 RETURN_BOOL((int)ret);
840 }
841
PHP_FUNCTION(intlcal_is_equivalent_to)842 U_CFUNC PHP_FUNCTION(intlcal_is_equivalent_to)
843 {
844 zval *other_object;
845 Calendar_object *other_co;
846 CALENDAR_METHOD_INIT_VARS;
847
848 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
849 "OO", &object, Calendar_ce_ptr, &other_object, Calendar_ce_ptr)
850 == FAILURE) {
851 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
852 "intlcal_is_equivalent_to: bad arguments", 0);
853 RETURN_FALSE;
854 }
855
856 other_co = Z_INTL_CALENDAR_P(other_object);
857 if (other_co->ucal == NULL) {
858 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intlcal_is_equivalent_to:"
859 " Other IntlCalendar is unconstructed", 0);
860 RETURN_FALSE;
861 }
862
863 CALENDAR_METHOD_FETCH_OBJECT;
864
865 RETURN_BOOL((int)co->ucal->isEquivalentTo(*other_co->ucal));
866 }
867
PHP_FUNCTION(intlcal_is_lenient)868 U_CFUNC PHP_FUNCTION(intlcal_is_lenient)
869 {
870 CALENDAR_METHOD_INIT_VARS;
871
872 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
873 "O", &object, Calendar_ce_ptr) == FAILURE) {
874 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
875 "intlcal_is_lenient: bad arguments", 0);
876 RETURN_FALSE;
877 }
878
879 CALENDAR_METHOD_FETCH_OBJECT;
880
881 RETURN_BOOL((int)co->ucal->isLenient());
882 }
883
PHP_FUNCTION(intlcal_is_set)884 U_CFUNC PHP_FUNCTION(intlcal_is_set)
885 {
886 zend_long field;
887 CALENDAR_METHOD_INIT_VARS;
888
889 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
890 "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) {
891 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
892 "intlcal_is_set: bad arguments", 0);
893 RETURN_FALSE;
894 }
895
896 if (field < 0 || field >= UCAL_FIELD_COUNT) {
897 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
898 "intlcal_is_set: invalid field", 0);
899 RETURN_FALSE;
900 }
901
902 CALENDAR_METHOD_FETCH_OBJECT;
903
904 RETURN_BOOL((int)co->ucal->isSet((UCalendarDateFields)field));
905 }
906
907 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 44
PHP_FUNCTION(intlcal_is_weekend)908 U_CFUNC PHP_FUNCTION(intlcal_is_weekend)
909 {
910 double date;
911 zend_bool date_is_null = 1;
912 CALENDAR_METHOD_INIT_VARS;
913
914 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
915 "O|d!", &object, Calendar_ce_ptr, &date, &date_is_null) == FAILURE) {
916 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
917 "intlcal_is_weekend: bad arguments", 0);
918 RETURN_FALSE;
919 }
920
921 CALENDAR_METHOD_FETCH_OBJECT;
922
923 if (date_is_null) {
924 RETURN_BOOL((int)co->ucal->isWeekend());
925 } else {
926 UBool ret = co->ucal->isWeekend((UDate)date, CALENDAR_ERROR_CODE(co));
927 INTL_METHOD_CHECK_STATUS(co, "intlcal_is_weekend: "
928 "Error calling ICU method");
929 RETURN_BOOL((int)ret);
930 }
931 }
932 #endif
933
934
PHP_FUNCTION(intlcal_set_first_day_of_week)935 U_CFUNC PHP_FUNCTION(intlcal_set_first_day_of_week)
936 {
937 zend_long dow;
938 CALENDAR_METHOD_INIT_VARS;
939
940 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
941 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
942 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
943 "intlcal_set_first_day_of_week: bad arguments", 0);
944 RETURN_FALSE;
945 }
946
947 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
948 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
949 "intlcal_set_first_day_of_week: invalid day of week", 0);
950 RETURN_FALSE;
951 }
952
953 CALENDAR_METHOD_FETCH_OBJECT;
954
955 co->ucal->setFirstDayOfWeek((UCalendarDaysOfWeek)dow);
956
957 RETURN_TRUE;
958 }
959
PHP_FUNCTION(intlcal_set_lenient)960 U_CFUNC PHP_FUNCTION(intlcal_set_lenient)
961 {
962 zend_bool is_lenient;
963 CALENDAR_METHOD_INIT_VARS;
964
965 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
966 "Ob", &object, Calendar_ce_ptr, &is_lenient) == FAILURE) {
967 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
968 "intlcal_set_lenient: bad arguments", 0);
969 RETURN_FALSE;
970 }
971
972 CALENDAR_METHOD_FETCH_OBJECT;
973
974 co->ucal->setLenient((UBool) is_lenient);
975
976 RETURN_TRUE;
977 }
978
PHP_FUNCTION(intlcal_set_minimal_days_in_first_week)979 U_CFUNC PHP_FUNCTION(intlcal_set_minimal_days_in_first_week)
980 {
981 zend_long num_days;
982 CALENDAR_METHOD_INIT_VARS;
983
984 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
985 "Ol", &object, Calendar_ce_ptr, &num_days) == FAILURE) {
986 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
987 "intlcal_set_minimal_days_in_first_week: bad arguments", 0);
988 RETURN_FALSE;
989 }
990
991 if (num_days < 1 || num_days > 7) {
992 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
993 "intlcal_set_minimal_days_in_first_week: invalid number of days; "
994 "must be between 1 and 7", 0);
995 RETURN_FALSE;
996 }
997
998 CALENDAR_METHOD_FETCH_OBJECT;
999
1000 co->ucal->setMinimalDaysInFirstWeek((uint8_t)num_days);
1001
1002 RETURN_TRUE;
1003 }
1004
PHP_FUNCTION(intlcal_equals)1005 U_CFUNC PHP_FUNCTION(intlcal_equals)
1006 {
1007 zval *other_object;
1008 Calendar_object *other_co;
1009 CALENDAR_METHOD_INIT_VARS;
1010
1011 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1012 "OO", &object, Calendar_ce_ptr, &other_object, Calendar_ce_ptr)
1013 == FAILURE) {
1014 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1015 "intlcal_equals: bad arguments", 0);
1016 RETURN_FALSE;
1017 }
1018
1019 CALENDAR_METHOD_FETCH_OBJECT;
1020 other_co = Z_INTL_CALENDAR_P(other_object);
1021 if (other_co->ucal == NULL) {
1022 intl_errors_set(&co->err, U_ILLEGAL_ARGUMENT_ERROR,
1023 "intlcal_equals: The second IntlCalendar is unconstructed", 0);
1024 RETURN_FALSE;
1025 }
1026
1027 UBool result = co->ucal->equals(*other_co->ucal, CALENDAR_ERROR_CODE(co));
1028 INTL_METHOD_CHECK_STATUS(co, "intlcal_equals: error calling ICU Calendar::equals");
1029
1030 RETURN_BOOL((int)result);
1031 }
1032
1033 #if U_ICU_VERSION_MAJOR_NUM >= 49
1034
PHP_FUNCTION(intlcal_get_repeated_wall_time_option)1035 U_CFUNC PHP_FUNCTION(intlcal_get_repeated_wall_time_option)
1036 {
1037 CALENDAR_METHOD_INIT_VARS;
1038
1039 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1040 "O", &object, Calendar_ce_ptr) == FAILURE) {
1041 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1042 "intlcal_get_repeated_wall_time_option: bad arguments", 0);
1043 RETURN_FALSE;
1044 }
1045
1046 CALENDAR_METHOD_FETCH_OBJECT;
1047
1048 RETURN_LONG(co->ucal->getRepeatedWallTimeOption());
1049 }
1050
PHP_FUNCTION(intlcal_get_skipped_wall_time_option)1051 U_CFUNC PHP_FUNCTION(intlcal_get_skipped_wall_time_option)
1052 {
1053 CALENDAR_METHOD_INIT_VARS;
1054
1055 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1056 "O", &object, Calendar_ce_ptr) == FAILURE) {
1057 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1058 "intlcal_get_skipped_wall_time_option: bad arguments", 0);
1059 RETURN_FALSE;
1060 }
1061
1062 CALENDAR_METHOD_FETCH_OBJECT;
1063
1064 RETURN_LONG(co->ucal->getSkippedWallTimeOption());
1065 }
1066
PHP_FUNCTION(intlcal_set_repeated_wall_time_option)1067 U_CFUNC PHP_FUNCTION(intlcal_set_repeated_wall_time_option)
1068 {
1069 zend_long option;
1070 CALENDAR_METHOD_INIT_VARS;
1071
1072 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1073 "Ol", &object, Calendar_ce_ptr, &option) == FAILURE) {
1074 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1075 "intlcal_set_repeated_wall_time_option: bad arguments", 0);
1076 RETURN_FALSE;
1077 }
1078
1079 if (option != UCAL_WALLTIME_FIRST && option != UCAL_WALLTIME_LAST) {
1080 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1081 "intlcal_set_repeated_wall_time_option: invalid option", 0);
1082 RETURN_FALSE;
1083 }
1084
1085 CALENDAR_METHOD_FETCH_OBJECT;
1086
1087 co->ucal->setRepeatedWallTimeOption((UCalendarWallTimeOption)option);
1088
1089 RETURN_TRUE;
1090 }
1091
PHP_FUNCTION(intlcal_set_skipped_wall_time_option)1092 U_CFUNC PHP_FUNCTION(intlcal_set_skipped_wall_time_option)
1093 {
1094 zend_long option;
1095 CALENDAR_METHOD_INIT_VARS;
1096
1097 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1098 "Ol", &object, Calendar_ce_ptr, &option) == FAILURE) {
1099 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1100 "intlcal_set_skipped_wall_time_option: bad arguments", 0);
1101 RETURN_FALSE;
1102 }
1103
1104 if (option != UCAL_WALLTIME_FIRST && option != UCAL_WALLTIME_LAST
1105 && option != UCAL_WALLTIME_NEXT_VALID) {
1106 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1107 "intlcal_set_skipped_wall_time_option: invalid option", 0);
1108 RETURN_FALSE;
1109 }
1110
1111 CALENDAR_METHOD_FETCH_OBJECT;
1112
1113 co->ucal->setSkippedWallTimeOption((UCalendarWallTimeOption)option);
1114
1115 RETURN_TRUE;
1116 }
1117
1118 #endif
1119
PHP_FUNCTION(intlcal_from_date_time)1120 U_CFUNC PHP_FUNCTION(intlcal_from_date_time)
1121 {
1122 zval *zv_arg,
1123 zv_tmp,
1124 *zv_datetime = NULL,
1125 zv_timestamp;
1126 php_date_obj *datetime;
1127 char *locale_str = NULL;
1128 size_t locale_str_len;
1129 TimeZone *timeZone;
1130 UErrorCode status = U_ZERO_ERROR;
1131 Calendar *cal;
1132 intl_error_reset(NULL);
1133
1134 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|s!",
1135 &zv_arg, &locale_str, &locale_str_len) == FAILURE) {
1136 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1137 "intlcal_from_date_time: bad arguments", 0);
1138 RETURN_NULL();
1139 }
1140
1141 if (!(Z_TYPE_P(zv_arg) == IS_OBJECT && instanceof_function(
1142 Z_OBJCE_P(zv_arg), php_date_get_date_ce()))) {
1143 object_init_ex(&zv_tmp, php_date_get_date_ce());
1144 zend_call_method_with_1_params(&zv_tmp, NULL, &Z_OBJCE(zv_tmp)->constructor, "__construct", NULL, zv_arg);
1145 zv_datetime = &zv_tmp;
1146 if (EG(exception)) {
1147 zend_object_store_ctor_failed(Z_OBJ(zv_tmp));
1148 goto error;
1149 }
1150 } else {
1151 zv_datetime = zv_arg;
1152 }
1153
1154 datetime = Z_PHPDATE_P(zv_datetime);
1155 if (!datetime->time) {
1156 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1157 "intlcal_from_date_time: DateTime object is unconstructed",
1158 0);
1159 goto error;
1160 }
1161
1162 zend_call_method_with_0_params(zv_datetime, php_date_get_date_ce(), NULL, "gettimestamp", &zv_timestamp);
1163 if (Z_TYPE(zv_timestamp) != IS_LONG) {
1164 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1165 "intlcal_from_date_time: bad DateTime; call to "
1166 "DateTime::getTimestamp() failed", 0);
1167 zval_ptr_dtor(&zv_timestamp);
1168 goto error;
1169 }
1170
1171 if (!datetime->time->is_localtime) {
1172 timeZone = TimeZone::getGMT()->clone();
1173 } else {
1174 timeZone = timezone_convert_datetimezone(datetime->time->zone_type,
1175 datetime, 1, NULL, "intlcal_from_date_time");
1176 if (timeZone == NULL) {
1177 goto error;
1178 }
1179 }
1180
1181 if (!locale_str) {
1182 locale_str = const_cast<char*>(intl_locale_get_default());
1183 }
1184
1185 cal = Calendar::createInstance(timeZone,
1186 Locale::createFromName(locale_str), status);
1187 if (cal == NULL) {
1188 delete timeZone;
1189 intl_error_set(NULL, status, "intlcal_from_date_time: "
1190 "error creating ICU Calendar object", 0);
1191 goto error;
1192 }
1193 cal->setTime(((UDate)Z_LVAL(zv_timestamp)) * 1000., status);
1194 if (U_FAILURE(status)) {
1195 /* time zone was adopted by cal; should not be deleted here */
1196 delete cal;
1197 intl_error_set(NULL, status, "intlcal_from_date_time: "
1198 "error creating ICU Calendar::setTime()", 0);
1199 goto error;
1200 }
1201
1202 calendar_object_create(return_value, cal);
1203
1204 error:
1205 if (zv_datetime && zv_datetime != zv_arg) {
1206 zval_ptr_dtor(zv_datetime);
1207 }
1208 }
1209
PHP_FUNCTION(intlcal_to_date_time)1210 U_CFUNC PHP_FUNCTION(intlcal_to_date_time)
1211 {
1212 zval retval;
1213 CALENDAR_METHOD_INIT_VARS;
1214
1215 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
1216 &object, Calendar_ce_ptr) == FAILURE) {
1217 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1218 "intlcal_to_date_time: bad arguments", 0);
1219 RETURN_FALSE;
1220 }
1221
1222 CALENDAR_METHOD_FETCH_OBJECT;
1223
1224 /* There are no exported functions in ext/date to this
1225 * in a more native fashion */
1226 double date = co->ucal->getTime(CALENDAR_ERROR_CODE(co)) / 1000.;
1227 int64_t ts;
1228 char ts_str[sizeof("@-9223372036854775808")];
1229 int ts_str_len;
1230 zval ts_zval, tmp;
1231
1232 INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed");
1233
1234 if (date > (double)U_INT64_MAX || date < (double)U_INT64_MIN) {
1235 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1236 "intlcal_to_date_time: The calendar date is out of the "
1237 "range for a 64-bit integer", 0);
1238 RETURN_FALSE;
1239 }
1240
1241 ZVAL_UNDEF(&retval);
1242 ts = (int64_t)date;
1243
1244 ts_str_len = slprintf(ts_str, sizeof(ts_str), "@%" PRIi64, ts);
1245 ZVAL_STRINGL(&ts_zval, ts_str, ts_str_len);
1246
1247 /* Now get the time zone */
1248 const TimeZone& tz = co->ucal->getTimeZone();
1249 zval *timezone_zval = timezone_convert_to_datetimezone(
1250 &tz, CALENDAR_ERROR_P(co), "intlcal_to_date_time", &tmp);
1251 if (timezone_zval == NULL) {
1252 zval_ptr_dtor(&ts_zval);
1253 RETURN_FALSE;
1254 }
1255
1256 /* resources allocated from now on */
1257
1258 /* Finally, instantiate object and call constructor */
1259 object_init_ex(return_value, php_date_get_date_ce());
1260 zend_call_method_with_2_params(return_value, NULL, &Z_OBJCE_P(return_value)->constructor, "__construct", NULL, &ts_zval, timezone_zval);
1261 if (EG(exception)) {
1262 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1263 "intlcal_to_date_time: DateTime constructor has thrown exception",
1264 1);
1265 zend_object_store_ctor_failed(Z_OBJ_P(return_value));
1266 zval_ptr_dtor(return_value);
1267 zval_ptr_dtor(&ts_zval);
1268
1269 RETVAL_FALSE;
1270 goto error;
1271 }
1272 zval_ptr_dtor(&ts_zval);
1273
1274 /* due to bug #40743, we have to set the time zone again */
1275 zend_call_method_with_1_params(return_value, NULL, NULL, "settimezone",
1276 &retval, timezone_zval);
1277 if (Z_ISUNDEF(retval) || Z_TYPE(retval) == IS_FALSE) {
1278 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1279 "intlcal_to_date_time: call to DateTime::setTimeZone has failed",
1280 1);
1281 zval_ptr_dtor(return_value);
1282 RETVAL_FALSE;
1283 goto error;
1284 }
1285
1286 error:
1287 zval_ptr_dtor(timezone_zval);
1288 zval_ptr_dtor(&retval);
1289 }
1290
PHP_FUNCTION(intlcal_get_error_code)1291 U_CFUNC PHP_FUNCTION(intlcal_get_error_code)
1292 {
1293 CALENDAR_METHOD_INIT_VARS;
1294
1295 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
1296 &object, Calendar_ce_ptr) == FAILURE) {
1297 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1298 "intlcal_get_error_code: bad arguments", 0);
1299 RETURN_FALSE;
1300 }
1301
1302 /* Fetch the object (without resetting its last error code ). */
1303 co = Z_INTL_CALENDAR_P(object);
1304 if (co == NULL)
1305 RETURN_FALSE;
1306
1307 RETURN_LONG((zend_long)CALENDAR_ERROR_CODE(co));
1308 }
1309
PHP_FUNCTION(intlcal_get_error_message)1310 U_CFUNC PHP_FUNCTION(intlcal_get_error_message)
1311 {
1312 zend_string* message = NULL;
1313 CALENDAR_METHOD_INIT_VARS;
1314
1315 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
1316 &object, Calendar_ce_ptr) == FAILURE) {
1317 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
1318 "intlcal_get_error_message: bad arguments", 0 );
1319 RETURN_FALSE;
1320 }
1321
1322
1323 /* Fetch the object (without resetting its last error code ). */
1324 co = Z_INTL_CALENDAR_P(object);
1325 if (co == NULL)
1326 RETURN_FALSE;
1327
1328 /* Return last error message. */
1329 message = intl_error_get_message(CALENDAR_ERROR_P(co));
1330 RETURN_STR(message);
1331 }
1332