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