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