calendar_methods.cpp 38 KB

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