1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2016 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Shane Caraveo <shane@caraveo.com> |
16 | Colin Viebrock <colin@easydns.com> |
17 | Hartmut Holzgraefe <hholzgra@php.net> |
18 | Wez Furlong <wez@thebrainroom.com> |
19 +----------------------------------------------------------------------+
20 */
21 /* $Id$ */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #ifdef PHP_WIN32
28 #define _WINNLS_
29 #endif
30
31 #include "php.h"
32 #include "ext/standard/info.h"
33 #include "php_calendar.h"
34 #include "sdncal.h"
35
36 #include <stdio.h>
37
38 /* {{{ arginfo */
39 ZEND_BEGIN_ARG_INFO_EX(arginfo_unixtojd, 0, 0, 0)
40 ZEND_ARG_INFO(0, timestamp)
41 ZEND_END_ARG_INFO()
42
43 ZEND_BEGIN_ARG_INFO(arginfo_jdtounix, 0)
44 ZEND_ARG_INFO(0, jday)
45 ZEND_END_ARG_INFO()
46
47 ZEND_BEGIN_ARG_INFO_EX(arginfo_cal_info, 0, 0, 0)
48 ZEND_ARG_INFO(0, calendar)
49 ZEND_END_ARG_INFO()
50
51 ZEND_BEGIN_ARG_INFO(arginfo_cal_days_in_month, 0)
52 ZEND_ARG_INFO(0, calendar)
53 ZEND_ARG_INFO(0, month)
54 ZEND_ARG_INFO(0, year)
55 ZEND_END_ARG_INFO()
56
57 ZEND_BEGIN_ARG_INFO(arginfo_cal_to_jd, 0)
58 ZEND_ARG_INFO(0, calendar)
59 ZEND_ARG_INFO(0, month)
60 ZEND_ARG_INFO(0, day)
61 ZEND_ARG_INFO(0, year)
62 ZEND_END_ARG_INFO()
63
64 ZEND_BEGIN_ARG_INFO(arginfo_cal_from_jd, 0)
65 ZEND_ARG_INFO(0, jd)
66 ZEND_ARG_INFO(0, calendar)
67 ZEND_END_ARG_INFO()
68
69 ZEND_BEGIN_ARG_INFO(arginfo_jdtogregorian, 0)
70 ZEND_ARG_INFO(0, juliandaycount)
71 ZEND_END_ARG_INFO()
72
73 ZEND_BEGIN_ARG_INFO(arginfo_gregoriantojd, 0)
74 ZEND_ARG_INFO(0, month)
75 ZEND_ARG_INFO(0, day)
76 ZEND_ARG_INFO(0, year)
77 ZEND_END_ARG_INFO()
78
79 ZEND_BEGIN_ARG_INFO(arginfo_jdtojulian, 0)
80 ZEND_ARG_INFO(0, juliandaycount)
81 ZEND_END_ARG_INFO()
82
83 ZEND_BEGIN_ARG_INFO(arginfo_juliantojd, 0)
84 ZEND_ARG_INFO(0, month)
85 ZEND_ARG_INFO(0, day)
86 ZEND_ARG_INFO(0, year)
87 ZEND_END_ARG_INFO()
88
89 ZEND_BEGIN_ARG_INFO_EX(arginfo_jdtojewish, 0, 0, 1)
90 ZEND_ARG_INFO(0, juliandaycount)
91 ZEND_ARG_INFO(0, hebrew)
92 ZEND_ARG_INFO(0, fl)
93 ZEND_END_ARG_INFO()
94
95 ZEND_BEGIN_ARG_INFO(arginfo_jewishtojd, 0)
96 ZEND_ARG_INFO(0, month)
97 ZEND_ARG_INFO(0, day)
98 ZEND_ARG_INFO(0, year)
99 ZEND_END_ARG_INFO()
100
101 ZEND_BEGIN_ARG_INFO(arginfo_jdtofrench, 0)
102 ZEND_ARG_INFO(0, juliandaycount)
103 ZEND_END_ARG_INFO()
104
105 ZEND_BEGIN_ARG_INFO(arginfo_frenchtojd, 0)
106 ZEND_ARG_INFO(0, month)
107 ZEND_ARG_INFO(0, day)
108 ZEND_ARG_INFO(0, year)
109 ZEND_END_ARG_INFO()
110
111 ZEND_BEGIN_ARG_INFO_EX(arginfo_jddayofweek, 0, 0, 1)
112 ZEND_ARG_INFO(0, juliandaycount)
113 ZEND_ARG_INFO(0, mode)
114 ZEND_END_ARG_INFO()
115
116 ZEND_BEGIN_ARG_INFO(arginfo_jdmonthname, 0)
117 ZEND_ARG_INFO(0, juliandaycount)
118 ZEND_ARG_INFO(0, mode)
119 ZEND_END_ARG_INFO()
120
121 ZEND_BEGIN_ARG_INFO_EX(arginfo_easter_date, 0, 0, 0)
122 ZEND_ARG_INFO(0, year)
123 ZEND_END_ARG_INFO()
124
125 ZEND_BEGIN_ARG_INFO_EX(arginfo_easter_days, 0, 0, 0)
126 ZEND_ARG_INFO(0, year)
127 ZEND_ARG_INFO(0, method)
128 ZEND_END_ARG_INFO()
129
130 /* }}} */
131
132 const zend_function_entry calendar_functions[] = {
133 PHP_FE(jdtogregorian, arginfo_jdtogregorian)
134 PHP_FE(gregoriantojd, arginfo_gregoriantojd)
135 PHP_FE(jdtojulian, arginfo_jdtojulian)
136 PHP_FE(juliantojd, arginfo_juliantojd)
137 PHP_FE(jdtojewish, arginfo_jdtojewish)
138 PHP_FE(jewishtojd, arginfo_jewishtojd)
139 PHP_FE(jdtofrench, arginfo_jdtofrench)
140 PHP_FE(frenchtojd, arginfo_frenchtojd)
141 PHP_FE(jddayofweek, arginfo_jddayofweek)
142 PHP_FE(jdmonthname, arginfo_jdmonthname)
143 PHP_FE(easter_date, arginfo_easter_date)
144 PHP_FE(easter_days, arginfo_easter_days)
145 PHP_FE(unixtojd, arginfo_unixtojd)
146 PHP_FE(jdtounix, arginfo_jdtounix)
147 PHP_FE(cal_to_jd, arginfo_cal_to_jd)
148 PHP_FE(cal_from_jd, arginfo_cal_from_jd)
149 PHP_FE(cal_days_in_month, arginfo_cal_days_in_month)
150 PHP_FE(cal_info, arginfo_cal_info)
151 PHP_FE_END
152 };
153
154
155 zend_module_entry calendar_module_entry = {
156 STANDARD_MODULE_HEADER,
157 "calendar",
158 calendar_functions,
159 PHP_MINIT(calendar),
160 NULL,
161 NULL,
162 NULL,
163 PHP_MINFO(calendar),
164 NO_VERSION_YET,
165 STANDARD_MODULE_PROPERTIES,
166 };
167
168 #ifdef COMPILE_DL_CALENDAR
169 ZEND_GET_MODULE(calendar)
170 #endif
171
172 /* this order must match the conversion table below */
173 enum cal_name_type_t {
174 CAL_GREGORIAN = 0,
175 CAL_JULIAN,
176 CAL_JEWISH,
177 CAL_FRENCH,
178 CAL_NUM_CALS
179 };
180
181 typedef long int (*cal_to_jd_func_t) (int month, int day, int year);
182 typedef void (*cal_from_jd_func_t) (long int jd, int *year, int *month, int *day);
183 typedef char *(*cal_as_string_func_t) (int year, int month, int day);
184
185 struct cal_entry_t {
186 char *name;
187 char *symbol;
188 cal_to_jd_func_t to_jd;
189 cal_from_jd_func_t from_jd;
190 int num_months;
191 int max_days_in_month;
192 char **month_name_short;
193 char **month_name_long;
194 };
195
196 static struct cal_entry_t cal_conversion_table[CAL_NUM_CALS] = {
197 {"Gregorian", "CAL_GREGORIAN", GregorianToSdn, SdnToGregorian, 12, 31,
198 MonthNameShort, MonthNameLong},
199 {"Julian", "CAL_JULIAN", JulianToSdn, SdnToJulian, 12, 31,
200 MonthNameShort, MonthNameLong},
201 {"Jewish", "CAL_JEWISH", JewishToSdn, SdnToJewish, 13, 30,
202 JewishMonthNameLeap, JewishMonthNameLeap},
203 {"French", "CAL_FRENCH", FrenchToSdn, SdnToFrench, 13, 30,
204 FrenchMonthName, FrenchMonthName}
205 };
206
207 #define JEWISH_MONTH_NAME(year) ((monthsPerYear[((year)-1) % 19] == 13)?JewishMonthNameLeap:JewishMonthName)
208 #define JEWISH_HEB_MONTH_NAME(year) ((monthsPerYear[((year)-1) % 19] == 13)?JewishMonthHebNameLeap:JewishMonthHebName)
209
210 /* For jddayofweek */
211 enum { CAL_DOW_DAYNO, CAL_DOW_LONG, CAL_DOW_SHORT };
212
213 /* For jdmonthname */
214 enum { CAL_MONTH_GREGORIAN_SHORT, CAL_MONTH_GREGORIAN_LONG,
215 CAL_MONTH_JULIAN_SHORT, CAL_MONTH_JULIAN_LONG, CAL_MONTH_JEWISH,
216 CAL_MONTH_FRENCH
217 };
218
219 /* for heb_number_to_chars */
220 static char alef_bet[25] = "0����������������������";
221
222 #define CAL_JEWISH_ADD_ALAFIM_GERESH 0x2
223 #define CAL_JEWISH_ADD_ALAFIM 0x4
224 #define CAL_JEWISH_ADD_GERESHAYIM 0x8
225
PHP_MINIT_FUNCTION(calendar)226 PHP_MINIT_FUNCTION(calendar)
227 {
228 REGISTER_LONG_CONSTANT("CAL_GREGORIAN", CAL_GREGORIAN, CONST_CS | CONST_PERSISTENT);
229 REGISTER_LONG_CONSTANT("CAL_JULIAN", CAL_JULIAN, CONST_CS | CONST_PERSISTENT);
230 REGISTER_LONG_CONSTANT("CAL_JEWISH", CAL_JEWISH, CONST_CS | CONST_PERSISTENT);
231 REGISTER_LONG_CONSTANT("CAL_FRENCH", CAL_FRENCH, CONST_CS | CONST_PERSISTENT);
232 REGISTER_LONG_CONSTANT("CAL_NUM_CALS", CAL_NUM_CALS, CONST_CS | CONST_PERSISTENT);
233 /* constants for jddayofweek */
234 REGISTER_LONG_CONSTANT("CAL_DOW_DAYNO", CAL_DOW_DAYNO, CONST_CS | CONST_PERSISTENT);
235 REGISTER_LONG_CONSTANT("CAL_DOW_SHORT", CAL_DOW_SHORT, CONST_CS | CONST_PERSISTENT);
236 REGISTER_LONG_CONSTANT("CAL_DOW_LONG", CAL_DOW_LONG, CONST_CS | CONST_PERSISTENT);
237 /* constants for jdmonthname */
238 REGISTER_LONG_CONSTANT("CAL_MONTH_GREGORIAN_SHORT", CAL_MONTH_GREGORIAN_SHORT, CONST_CS | CONST_PERSISTENT);
239 REGISTER_LONG_CONSTANT("CAL_MONTH_GREGORIAN_LONG", CAL_MONTH_GREGORIAN_LONG, CONST_CS | CONST_PERSISTENT);
240 REGISTER_LONG_CONSTANT("CAL_MONTH_JULIAN_SHORT", CAL_MONTH_JULIAN_SHORT, CONST_CS | CONST_PERSISTENT);
241 REGISTER_LONG_CONSTANT("CAL_MONTH_JULIAN_LONG", CAL_MONTH_JULIAN_LONG, CONST_CS | CONST_PERSISTENT);
242 REGISTER_LONG_CONSTANT("CAL_MONTH_JEWISH", CAL_MONTH_JEWISH, CONST_CS | CONST_PERSISTENT);
243 REGISTER_LONG_CONSTANT("CAL_MONTH_FRENCH", CAL_MONTH_FRENCH, CONST_CS | CONST_PERSISTENT);
244 /* constants for easter calculation */
245 REGISTER_LONG_CONSTANT("CAL_EASTER_DEFAULT", CAL_EASTER_DEFAULT, CONST_CS | CONST_PERSISTENT);
246 REGISTER_LONG_CONSTANT("CAL_EASTER_ROMAN", CAL_EASTER_ROMAN, CONST_CS | CONST_PERSISTENT);
247 REGISTER_LONG_CONSTANT("CAL_EASTER_ALWAYS_GREGORIAN", CAL_EASTER_ALWAYS_GREGORIAN, CONST_CS | CONST_PERSISTENT);
248 REGISTER_LONG_CONSTANT("CAL_EASTER_ALWAYS_JULIAN", CAL_EASTER_ALWAYS_JULIAN, CONST_CS | CONST_PERSISTENT);
249 /* constants for Jewish date formatting */
250 REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_ALAFIM_GERESH", CAL_JEWISH_ADD_ALAFIM_GERESH, CONST_CS | CONST_PERSISTENT);
251 REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_ALAFIM", CAL_JEWISH_ADD_ALAFIM, CONST_CS | CONST_PERSISTENT);
252 REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_GERESHAYIM", CAL_JEWISH_ADD_GERESHAYIM, CONST_CS | CONST_PERSISTENT);
253 return SUCCESS;
254 }
255
PHP_MINFO_FUNCTION(calendar)256 PHP_MINFO_FUNCTION(calendar)
257 {
258 php_info_print_table_start();
259 php_info_print_table_row(2, "Calendar support", "enabled");
260 php_info_print_table_end();
261 }
262
_php_cal_info(int cal,zval ** ret)263 static void _php_cal_info(int cal, zval **ret)
264 {
265 zval *months, *smonths;
266 int i;
267 struct cal_entry_t *calendar;
268
269 calendar = &cal_conversion_table[cal];
270 array_init(*ret);
271
272 MAKE_STD_ZVAL(months);
273 MAKE_STD_ZVAL(smonths);
274 array_init(months);
275 array_init(smonths);
276
277 for (i = 1; i <= calendar->num_months; i++) {
278 add_index_string(months, i, calendar->month_name_long[i], 1);
279 add_index_string(smonths, i, calendar->month_name_short[i], 1);
280 }
281 add_assoc_zval(*ret, "months", months);
282 add_assoc_zval(*ret, "abbrevmonths", smonths);
283 add_assoc_long(*ret, "maxdaysinmonth", calendar->max_days_in_month);
284 add_assoc_string(*ret, "calname", calendar->name, 1);
285 add_assoc_string(*ret, "calsymbol", calendar->symbol, 1);
286
287 }
288
289 /* {{{ proto array cal_info([int calendar])
290 Returns information about a particular calendar */
PHP_FUNCTION(cal_info)291 PHP_FUNCTION(cal_info)
292 {
293 long cal = -1;
294
295
296 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &cal) == FAILURE) {
297 RETURN_FALSE;
298 }
299
300 if (cal == -1) {
301 int i;
302 zval *val;
303
304 array_init(return_value);
305
306 for (i = 0; i < CAL_NUM_CALS; i++) {
307 MAKE_STD_ZVAL(val);
308 _php_cal_info(i, &val);
309 add_index_zval(return_value, i, val);
310 }
311 return;
312 }
313
314
315 if (cal != -1 && (cal < 0 || cal >= CAL_NUM_CALS)) {
316 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
317 RETURN_FALSE;
318 }
319
320 _php_cal_info(cal, &return_value);
321
322 }
323 /* }}} */
324
325 /* {{{ proto int cal_days_in_month(int calendar, int month, int year)
326 Returns the number of days in a month for a given year and calendar */
PHP_FUNCTION(cal_days_in_month)327 PHP_FUNCTION(cal_days_in_month)
328 {
329 long cal, month, year;
330 struct cal_entry_t *calendar;
331 long sdn_start, sdn_next;
332
333 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &cal, &month, &year) == FAILURE) {
334 RETURN_FALSE;
335 }
336
337 if (cal < 0 || cal >= CAL_NUM_CALS) {
338 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
339 RETURN_FALSE;
340 }
341
342 calendar = &cal_conversion_table[cal];
343
344 sdn_start = calendar->to_jd(year, month, 1);
345
346 if (sdn_start == 0) {
347 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid date.");
348 RETURN_FALSE;
349 }
350
351 sdn_next = calendar->to_jd(year, 1 + month, 1);
352
353 if (sdn_next == 0) {
354 /* If the next month is invalid, then we need to try the first month of
355 * the next year, bearing in mind that the next year after 1 BCE is
356 * actually 1 AD and not 0. */
357 if (year == -1) {
358 sdn_next = calendar->to_jd(1, 1, 1);
359 }
360 else {
361 sdn_next = calendar->to_jd(year + 1, 1, 1);
362 if (cal == CAL_FRENCH && sdn_next == 0) {
363 /* The French calendar ends on 0014-13-05. */
364 sdn_next = 2380953;
365 }
366 }
367 }
368
369 RETURN_LONG(sdn_next - sdn_start);
370 }
371 /* }}} */
372
373 /* {{{ proto int cal_to_jd(int calendar, int month, int day, int year)
374 Converts from a supported calendar to Julian Day Count */
PHP_FUNCTION(cal_to_jd)375 PHP_FUNCTION(cal_to_jd)
376 {
377 long cal, month, day, year;
378
379 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &cal, &month, &day, &year) != SUCCESS) {
380 RETURN_FALSE;
381 }
382
383 if (cal < 0 || cal >= CAL_NUM_CALS) {
384 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
385 RETURN_FALSE;
386 }
387
388 RETURN_LONG(cal_conversion_table[cal].to_jd(year, month, day));
389 }
390 /* }}} */
391
392 /* {{{ proto array cal_from_jd(int jd, int calendar)
393 Converts from Julian Day Count to a supported calendar and return extended information */
PHP_FUNCTION(cal_from_jd)394 PHP_FUNCTION(cal_from_jd)
395 {
396 long jd, cal;
397 int month, day, year, dow;
398 char date[16];
399 struct cal_entry_t *calendar;
400
401 if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "ll", &jd, &cal) == FAILURE) {
402 RETURN_FALSE;
403 }
404
405 if (cal < 0 || cal >= CAL_NUM_CALS) {
406 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld", cal);
407 RETURN_FALSE;
408 }
409 calendar = &cal_conversion_table[cal];
410
411 array_init(return_value);
412
413 calendar->from_jd(jd, &year, &month, &day);
414
415 snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
416 add_assoc_string(return_value, "date", date, 1);
417
418 add_assoc_long(return_value, "month", month);
419 add_assoc_long(return_value, "day", day);
420 add_assoc_long(return_value, "year", year);
421
422 /* day of week */
423 if (cal != CAL_JEWISH || year > 0) {
424 dow = DayOfWeek(jd);
425 add_assoc_long(return_value, "dow", dow);
426 add_assoc_string(return_value, "abbrevdayname", DayNameShort[dow], 1);
427 add_assoc_string(return_value, "dayname", DayNameLong[dow], 1);
428 } else {
429 add_assoc_null(return_value, "dow");
430 add_assoc_string(return_value, "abbrevdayname", "", 1);
431 add_assoc_string(return_value, "dayname", "", 1);
432 }
433 /* month name */
434 if(cal == CAL_JEWISH) {
435 /* special case for Jewish calendar */
436 add_assoc_string(return_value, "abbrevmonth", (year > 0 ? JEWISH_MONTH_NAME(year)[month] : ""), 1);
437 add_assoc_string(return_value, "monthname", (year > 0 ? JEWISH_MONTH_NAME(year)[month] : ""), 1);
438 } else {
439 add_assoc_string(return_value, "abbrevmonth", calendar->month_name_short[month], 1);
440 add_assoc_string(return_value, "monthname", calendar->month_name_long[month], 1);
441 }
442 }
443 /* }}} */
444
445 /* {{{ proto string jdtogregorian(int juliandaycount)
446 Converts a julian day count to a gregorian calendar date */
PHP_FUNCTION(jdtogregorian)447 PHP_FUNCTION(jdtogregorian)
448 {
449 long julday;
450 int year, month, day;
451 char date[16];
452
453 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
454 RETURN_FALSE;
455 }
456
457 SdnToGregorian(julday, &year, &month, &day);
458 snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
459
460 RETURN_STRING(date, 1);
461 }
462 /* }}} */
463
464 /* {{{ proto int gregoriantojd(int month, int day, int year)
465 Converts a gregorian calendar date to julian day count */
PHP_FUNCTION(gregoriantojd)466 PHP_FUNCTION(gregoriantojd)
467 {
468 long year, month, day;
469
470 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
471 RETURN_FALSE;
472 }
473
474 RETURN_LONG(GregorianToSdn(year, month, day));
475 }
476 /* }}} */
477
478 /* {{{ proto string jdtojulian(int juliandaycount)
479 Convert a julian day count to a julian calendar date */
PHP_FUNCTION(jdtojulian)480 PHP_FUNCTION(jdtojulian)
481 {
482 long julday;
483 int year, month, day;
484 char date[16];
485
486 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
487 RETURN_FALSE;
488 }
489
490 SdnToJulian(julday, &year, &month, &day);
491 snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
492
493 RETURN_STRING(date, 1);
494 }
495 /* }}} */
496
497 /* {{{ proto int juliantojd(int month, int day, int year)
498 Converts a julian calendar date to julian day count */
PHP_FUNCTION(juliantojd)499 PHP_FUNCTION(juliantojd)
500 {
501 long year, month, day;
502
503 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
504 RETURN_FALSE;
505 }
506
507 RETURN_LONG(JulianToSdn(year, month, day));
508 }
509 /* }}} */
510
511 /* {{{ heb_number_to_chars*/
512 /*
513 caution: the Hebrew format produces non unique result.
514 for example both: year '5' and year '5000' produce '�'.
515 use the numeric one for calculations.
516 */
heb_number_to_chars(int n,int fl,char ** ret)517 static char *heb_number_to_chars(int n, int fl, char **ret)
518 {
519 char *p, old[18], *endofalafim;
520
521 p = endofalafim = old;
522 /*
523 prevents the option breaking the jewish beliefs, and some other
524 critical resources ;)
525 */
526 if (n > 9999 || n < 1) {
527 *ret = NULL;
528 return NULL;
529 }
530
531 /* alafim (thousands) case */
532 if (n / 1000) {
533 *p = alef_bet[n / 1000];
534 p++;
535
536 if (CAL_JEWISH_ADD_ALAFIM_GERESH & fl) {
537 *p = '\'';
538 p++;
539 }
540 if (CAL_JEWISH_ADD_ALAFIM & fl) {
541 strcpy(p, " ����� ");
542 p += 7;
543 }
544
545 endofalafim = p;
546 n = n % 1000;
547 }
548
549 /* tav-tav (tav=400) case */
550 while (n >= 400) {
551 *p = alef_bet[22];
552 p++;
553 n -= 400;
554 }
555
556 /* meot (hundreads) case */
557 if (n >= 100) {
558 *p = alef_bet[18 + n / 100];
559 p++;
560 n = n % 100;
561 }
562
563 /* tet-vav & tet-zain case (special case for 15 and 16) */
564 if (n == 15 || n == 16) {
565 *p = alef_bet[9];
566 p++;
567 *p = alef_bet[n - 9];
568 p++;
569 } else {
570 /* asarot (tens) case */
571 if (n >= 10) {
572 *p = alef_bet[9 + n / 10];
573 p++;
574 n = n % 10;
575 }
576
577 /* yehidot (ones) case */
578 if (n > 0) {
579 *p = alef_bet[n];
580 p++;
581 }
582 }
583
584 if (CAL_JEWISH_ADD_GERESHAYIM & fl) {
585 switch (p - endofalafim) {
586 case 0:
587 break;
588 case 1:
589 *p = '\'';
590 p++;
591 break;
592 default:
593 *(p) = *(p - 1);
594 *(p - 1) = '"';
595 p++;
596 }
597 }
598
599 *p = '\0';
600 *ret = estrndup(old, (p - old) + 1);
601 p = *ret;
602 return p;
603 }
604 /* }}} */
605
606 /* {{{ proto string jdtojewish(int juliandaycount [, bool hebrew [, int fl]])
607 Converts a julian day count to a jewish calendar date */
PHP_FUNCTION(jdtojewish)608 PHP_FUNCTION(jdtojewish)
609 {
610 long julday, fl = 0;
611 zend_bool heb = 0;
612 int year, month, day;
613 char date[16], hebdate[32];
614 char *dayp, *yearp;
615
616 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|bl", &julday, &heb, &fl) == FAILURE) {
617 RETURN_FALSE;
618 }
619
620 SdnToJewish(julday, &year, &month, &day);
621 if (!heb) {
622 snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
623 RETURN_STRING(date, 1);
624 } else {
625 if (year <= 0 || year > 9999) {
626 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Year out of range (0-9999).");
627 RETURN_FALSE;
628 }
629
630 snprintf(hebdate, sizeof(hebdate), "%s %s %s", heb_number_to_chars(day, fl, &dayp), JEWISH_HEB_MONTH_NAME(year)[month], heb_number_to_chars(year, fl, &yearp));
631
632 if (dayp) {
633 efree(dayp);
634 }
635 if (yearp) {
636 efree(yearp);
637 }
638
639 RETURN_STRING(hebdate, 1);
640
641 }
642 }
643 /* }}} */
644
645 /* {{{ proto int jewishtojd(int month, int day, int year)
646 Converts a jewish calendar date to a julian day count */
PHP_FUNCTION(jewishtojd)647 PHP_FUNCTION(jewishtojd)
648 {
649 long year, month, day;
650
651 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
652 RETURN_FALSE;
653 }
654
655 RETURN_LONG(JewishToSdn(year, month, day));
656 }
657 /* }}} */
658
659 /* {{{ proto string jdtofrench(int juliandaycount)
660 Converts a julian day count to a french republic calendar date */
PHP_FUNCTION(jdtofrench)661 PHP_FUNCTION(jdtofrench)
662 {
663 long julday;
664 int year, month, day;
665 char date[16];
666
667 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
668 RETURN_FALSE;
669 }
670
671 SdnToFrench(julday, &year, &month, &day);
672 snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
673
674 RETURN_STRING(date, 1);
675 }
676 /* }}} */
677
678 /* {{{ proto int frenchtojd(int month, int day, int year)
679 Converts a french republic calendar date to julian day count */
PHP_FUNCTION(frenchtojd)680 PHP_FUNCTION(frenchtojd)
681 {
682 long year, month, day;
683
684 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
685 RETURN_FALSE;
686 }
687
688 RETURN_LONG(FrenchToSdn(year, month, day));
689 }
690 /* }}} */
691
692 /* {{{ proto mixed jddayofweek(int juliandaycount [, int mode])
693 Returns name or number of day of week from julian day count */
PHP_FUNCTION(jddayofweek)694 PHP_FUNCTION(jddayofweek)
695 {
696 long julday, mode = CAL_DOW_DAYNO;
697 int day;
698 char *daynamel, *daynames;
699
700 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &julday, &mode) == FAILURE) {
701 RETURN_FALSE;
702 }
703
704 day = DayOfWeek(julday);
705 daynamel = DayNameLong[day];
706 daynames = DayNameShort[day];
707
708 switch (mode) {
709 case CAL_DOW_LONG:
710 RETURN_STRING(daynamel, 1);
711 break;
712 case CAL_DOW_SHORT:
713 RETURN_STRING(daynames, 1);
714 break;
715 case CAL_DOW_DAYNO:
716 default:
717 RETURN_LONG(day);
718 break;
719 }
720 }
721 /* }}} */
722
723 /* {{{ proto string jdmonthname(int juliandaycount, int mode)
724 Returns name of month for julian day count */
PHP_FUNCTION(jdmonthname)725 PHP_FUNCTION(jdmonthname)
726 {
727 long julday, mode;
728 char *monthname = NULL;
729 int month, day, year;
730
731 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &julday, &mode) == FAILURE) {
732 RETURN_FALSE;
733 }
734
735 switch (mode) {
736 case CAL_MONTH_GREGORIAN_LONG: /* gregorian or julian month */
737 SdnToGregorian(julday, &year, &month, &day);
738 monthname = MonthNameLong[month];
739 break;
740 case CAL_MONTH_JULIAN_SHORT: /* gregorian or julian month */
741 SdnToJulian(julday, &year, &month, &day);
742 monthname = MonthNameShort[month];
743 break;
744 case CAL_MONTH_JULIAN_LONG: /* gregorian or julian month */
745 SdnToJulian(julday, &year, &month, &day);
746 monthname = MonthNameLong[month];
747 break;
748 case CAL_MONTH_JEWISH: /* jewish month */
749 SdnToJewish(julday, &year, &month, &day);
750 monthname = (year > 0 ? JEWISH_MONTH_NAME(year)[month] : "");
751 break;
752 case CAL_MONTH_FRENCH: /* french month */
753 SdnToFrench(julday, &year, &month, &day);
754 monthname = FrenchMonthName[month];
755 break;
756 default: /* default gregorian */
757 case CAL_MONTH_GREGORIAN_SHORT: /* gregorian or julian month */
758 SdnToGregorian(julday, &year, &month, &day);
759 monthname = MonthNameShort[month];
760 break;
761 }
762
763 RETURN_STRING(monthname, 1);
764 }
765 /* }}} */
766
767 /*
768 * Local variables:
769 * tab-width: 4
770 * c-basic-offset: 4
771 * End:
772 * vim600: sw=4 ts=4 fdm=marker
773 * vim<600: sw=4 ts=4
774 */
775