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 272370 2008-12-31 11:15: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 : 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 : {NULL, NULL, NULL}
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 : JewishMonthName, JewishMonthName},
203 : {"French", "CAL_FRENCH", FrenchToSdn, SdnToFrench, 13, 30,
204 : FrenchMonthName, FrenchMonthName}
205 : };
206 :
207 : /* For jddayofweek */
208 : enum { CAL_DOW_DAYNO, CAL_DOW_SHORT, CAL_DOW_LONG };
209 :
210 : /* For jdmonthname */
211 : enum { CAL_MONTH_GREGORIAN_SHORT, CAL_MONTH_GREGORIAN_LONG,
212 : CAL_MONTH_JULIAN_SHORT, CAL_MONTH_JULIAN_LONG, CAL_MONTH_JEWISH,
213 : CAL_MONTH_FRENCH
214 : };
215 :
216 : /* for heb_number_to_chars */
217 : static char alef_bet[25] = "0אבגדהוזחטיכלמנסעפצקרשת";
218 :
219 : #define CAL_JEWISH_ADD_ALAFIM_GERESH 0x2
220 : #define CAL_JEWISH_ADD_ALAFIM 0x4
221 : #define CAL_JEWISH_ADD_GERESHAYIM 0x8
222 :
223 : PHP_MINIT_FUNCTION(calendar)
224 17633 : {
225 17633 : REGISTER_LONG_CONSTANT("CAL_GREGORIAN", CAL_GREGORIAN, CONST_CS | CONST_PERSISTENT);
226 17633 : REGISTER_LONG_CONSTANT("CAL_JULIAN", CAL_JULIAN, CONST_CS | CONST_PERSISTENT);
227 17633 : REGISTER_LONG_CONSTANT("CAL_JEWISH", CAL_JEWISH, CONST_CS | CONST_PERSISTENT);
228 17633 : REGISTER_LONG_CONSTANT("CAL_FRENCH", CAL_FRENCH, CONST_CS | CONST_PERSISTENT);
229 17633 : REGISTER_LONG_CONSTANT("CAL_NUM_CALS", CAL_NUM_CALS, CONST_CS | CONST_PERSISTENT);
230 : /* constants for jddayofweek */
231 17633 : REGISTER_LONG_CONSTANT("CAL_DOW_DAYNO", CAL_DOW_DAYNO, CONST_CS | CONST_PERSISTENT);
232 17633 : REGISTER_LONG_CONSTANT("CAL_DOW_SHORT", CAL_DOW_SHORT, CONST_CS | CONST_PERSISTENT);
233 17633 : REGISTER_LONG_CONSTANT("CAL_DOW_LONG", CAL_DOW_LONG, CONST_CS | CONST_PERSISTENT);
234 : /* constants for jdmonthname */
235 17633 : REGISTER_LONG_CONSTANT("CAL_MONTH_GREGORIAN_SHORT", CAL_MONTH_GREGORIAN_SHORT, CONST_CS | CONST_PERSISTENT);
236 17633 : REGISTER_LONG_CONSTANT("CAL_MONTH_GREGORIAN_LONG", CAL_MONTH_GREGORIAN_LONG, CONST_CS | CONST_PERSISTENT);
237 17633 : REGISTER_LONG_CONSTANT("CAL_MONTH_JULIAN_SHORT", CAL_MONTH_JULIAN_SHORT, CONST_CS | CONST_PERSISTENT);
238 17633 : REGISTER_LONG_CONSTANT("CAL_MONTH_JULIAN_LONG", CAL_MONTH_JULIAN_LONG, CONST_CS | CONST_PERSISTENT);
239 17633 : REGISTER_LONG_CONSTANT("CAL_MONTH_JEWISH", CAL_MONTH_JEWISH, CONST_CS | CONST_PERSISTENT);
240 17633 : REGISTER_LONG_CONSTANT("CAL_MONTH_FRENCH", CAL_MONTH_FRENCH, CONST_CS | CONST_PERSISTENT);
241 : /* constants for easter calculation */
242 17633 : REGISTER_LONG_CONSTANT("CAL_EASTER_DEFAULT", CAL_EASTER_DEFAULT, CONST_CS | CONST_PERSISTENT);
243 17633 : REGISTER_LONG_CONSTANT("CAL_EASTER_ROMAN", CAL_EASTER_ROMAN, CONST_CS | CONST_PERSISTENT);
244 17633 : REGISTER_LONG_CONSTANT("CAL_EASTER_ALWAYS_GREGORIAN", CAL_EASTER_ALWAYS_GREGORIAN, CONST_CS | CONST_PERSISTENT);
245 17633 : REGISTER_LONG_CONSTANT("CAL_EASTER_ALWAYS_JULIAN", CAL_EASTER_ALWAYS_JULIAN, CONST_CS | CONST_PERSISTENT);
246 : /* constants for Jewish date formatting */
247 17633 : REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_ALAFIM_GERESH", CAL_JEWISH_ADD_ALAFIM_GERESH, CONST_CS | CONST_PERSISTENT);
248 17633 : REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_ALAFIM", CAL_JEWISH_ADD_ALAFIM, CONST_CS | CONST_PERSISTENT);
249 17633 : REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_GERESHAYIM", CAL_JEWISH_ADD_GERESHAYIM, CONST_CS | CONST_PERSISTENT);
250 17633 : return SUCCESS;
251 : }
252 :
253 : PHP_MINFO_FUNCTION(calendar)
254 42 : {
255 42 : php_info_print_table_start();
256 42 : php_info_print_table_row(2, "Calendar support", "enabled");
257 42 : php_info_print_table_end();
258 42 : }
259 :
260 : static void _php_cal_info(int cal, zval **ret)
261 5 : {
262 : zval *months, *smonths;
263 : int i;
264 : struct cal_entry_t *calendar;
265 :
266 5 : calendar = &cal_conversion_table[cal];
267 5 : array_init(*ret);
268 :
269 5 : MAKE_STD_ZVAL(months);
270 5 : MAKE_STD_ZVAL(smonths);
271 5 : array_init(months);
272 5 : array_init(smonths);
273 :
274 67 : for (i = 1; i <= calendar->num_months; i++) {
275 62 : add_index_string(months, i, calendar->month_name_long[i], 1);
276 62 : add_index_string(smonths, i, calendar->month_name_short[i], 1);
277 : }
278 5 : add_assoc_zval(*ret, "months", months);
279 5 : add_assoc_zval(*ret, "abbrevmonths", smonths);
280 5 : add_assoc_long(*ret, "maxdaysinmonth", calendar->max_days_in_month);
281 5 : add_assoc_string(*ret, "calname", calendar->name, 1);
282 5 : add_assoc_string(*ret, "calsymbol", calendar->symbol, 1);
283 :
284 5 : }
285 :
286 : /* {{{ proto array cal_info([int calendar])
287 : Returns information about a particular calendar */
288 : PHP_FUNCTION(cal_info)
289 3 : {
290 3 : long cal = -1;
291 :
292 :
293 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &cal) == FAILURE) {
294 0 : RETURN_FALSE;
295 : }
296 :
297 3 : if (cal == -1) {
298 : int i;
299 : zval *val;
300 :
301 1 : array_init(return_value);
302 :
303 5 : for (i = 0; i < CAL_NUM_CALS; i++) {
304 4 : MAKE_STD_ZVAL(val);
305 4 : _php_cal_info(i, &val);
306 4 : add_index_zval(return_value, i, val);
307 : }
308 1 : return;
309 : }
310 :
311 :
312 2 : if (cal != -1 && (cal < 0 || cal >= CAL_NUM_CALS)) {
313 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
314 1 : RETURN_FALSE;
315 : }
316 :
317 1 : _php_cal_info(cal, &return_value);
318 :
319 : }
320 : /* }}} */
321 :
322 : /* {{{ proto int cal_days_in_month(int calendar, int month, int year)
323 : Returns the number of days in a month for a given year and calendar */
324 : PHP_FUNCTION(cal_days_in_month)
325 6 : {
326 : long cal, month, year;
327 : struct cal_entry_t *calendar;
328 : long sdn_start, sdn_next;
329 :
330 6 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &cal, &month, &year) == FAILURE) {
331 0 : RETURN_FALSE;
332 : }
333 :
334 6 : if (cal < 0 || cal >= CAL_NUM_CALS) {
335 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
336 1 : RETURN_FALSE;
337 : }
338 :
339 5 : calendar = &cal_conversion_table[cal];
340 :
341 5 : sdn_start = calendar->to_jd(year, month, 1);
342 :
343 5 : if (sdn_start == 0) {
344 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid date.");
345 1 : RETURN_FALSE;
346 : }
347 :
348 4 : sdn_next = calendar->to_jd(year, 1 + month, 1);
349 :
350 4 : if (sdn_next == 0) {
351 : /* if invalid, try first month of the next year... */
352 1 : sdn_next = calendar->to_jd(year + 1, 1, 1);
353 : }
354 :
355 4 : RETURN_LONG(sdn_next - sdn_start);
356 : }
357 : /* }}} */
358 :
359 : /* {{{ proto int cal_to_jd(int calendar, int month, int day, int year)
360 : Converts from a supported calendar to Julian Day Count */
361 : PHP_FUNCTION(cal_to_jd)
362 4 : {
363 : long cal, month, day, year;
364 :
365 4 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &cal, &month, &day, &year) != SUCCESS) {
366 0 : RETURN_FALSE;
367 : }
368 :
369 4 : if (cal < 0 || cal >= CAL_NUM_CALS) {
370 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
371 0 : RETURN_FALSE;
372 : }
373 :
374 4 : RETURN_LONG(cal_conversion_table[cal].to_jd(year, month, day));
375 : }
376 : /* }}} */
377 :
378 : /* {{{ proto array cal_from_jd(int jd, int calendar)
379 : Converts from Julian Day Count to a supported calendar and return extended information */
380 : PHP_FUNCTION(cal_from_jd)
381 4 : {
382 : long jd, cal;
383 : int month, day, year, dow;
384 : char date[16];
385 : struct cal_entry_t *calendar;
386 :
387 4 : if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "ll", &jd, &cal) == FAILURE) {
388 0 : RETURN_FALSE;
389 : }
390 :
391 4 : if (cal < 0 || cal >= CAL_NUM_CALS) {
392 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld", cal);
393 0 : RETURN_FALSE;
394 : }
395 4 : calendar = &cal_conversion_table[cal];
396 :
397 4 : array_init(return_value);
398 :
399 4 : calendar->from_jd(jd, &year, &month, &day);
400 :
401 4 : snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
402 4 : add_assoc_string(return_value, "date", date, 1);
403 :
404 4 : add_assoc_long(return_value, "month", month);
405 4 : add_assoc_long(return_value, "day", day);
406 4 : add_assoc_long(return_value, "year", year);
407 :
408 : /* day of week */
409 4 : dow = DayOfWeek(jd);
410 4 : add_assoc_long(return_value, "dow", dow);
411 4 : add_assoc_string(return_value, "abbrevdayname", DayNameShort[dow], 1);
412 4 : add_assoc_string(return_value, "dayname", DayNameLong[dow], 1);
413 : /* month name */
414 4 : add_assoc_string(return_value, "abbrevmonth", calendar->month_name_short[month], 1);
415 4 : add_assoc_string(return_value, "monthname", calendar->month_name_long[month], 1);
416 : }
417 : /* }}} */
418 :
419 : /* {{{ proto string jdtogregorian(int juliandaycount)
420 : Converts a julian day count to a gregorian calendar date */
421 : PHP_FUNCTION(jdtogregorian)
422 5 : {
423 : long julday;
424 : int year, month, day;
425 : char date[16];
426 :
427 5 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
428 0 : RETURN_FALSE;
429 : }
430 :
431 5 : SdnToGregorian(julday, &year, &month, &day);
432 5 : snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
433 :
434 5 : RETURN_STRING(date, 1);
435 : }
436 : /* }}} */
437 :
438 : /* {{{ proto int gregoriantojd(int month, int day, int year)
439 : Converts a gregorian calendar date to julian day count */
440 : PHP_FUNCTION(gregoriantojd)
441 15 : {
442 : long year, month, day;
443 :
444 15 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
445 0 : RETURN_FALSE;
446 : }
447 :
448 15 : RETURN_LONG(GregorianToSdn(year, month, day));
449 : }
450 : /* }}} */
451 :
452 : /* {{{ proto string jdtojulian(int juliandaycount)
453 : Convert a julian day count to a julian calendar date */
454 : PHP_FUNCTION(jdtojulian)
455 5 : {
456 : long julday;
457 : int year, month, day;
458 : char date[16];
459 :
460 5 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
461 0 : RETURN_FALSE;
462 : }
463 :
464 5 : SdnToJulian(julday, &year, &month, &day);
465 5 : snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
466 :
467 5 : RETURN_STRING(date, 1);
468 : }
469 : /* }}} */
470 :
471 : /* {{{ proto int juliantojd(int month, int day, int year)
472 : Converts a julian calendar date to julian day count */
473 : PHP_FUNCTION(juliantojd)
474 5 : {
475 : long year, month, day;
476 :
477 5 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
478 0 : RETURN_FALSE;
479 : }
480 :
481 5 : RETURN_LONG(JulianToSdn(year, month, day));
482 : }
483 : /* }}} */
484 :
485 : /* {{{ heb_number_to_chars*/
486 : /*
487 : caution: the Hebrew format produces non unique result.
488 : for example both: year '5' and year '5000' produce 'ה'.
489 : use the numeric one for calculations.
490 : */
491 : static char *heb_number_to_chars(int n, int fl, char **ret)
492 18 : {
493 : char *p, old[18], *endofalafim;
494 :
495 18 : p = endofalafim = old;
496 : /*
497 : prevents the option breaking the jewish beliefs, and some other
498 : critical resources ;)
499 : */
500 18 : if (n > 9999 || n < 1) {
501 0 : *ret = NULL;
502 0 : return NULL;
503 : }
504 :
505 : /* alafim (thousands) case */
506 18 : if (n / 1000) {
507 9 : *p = alef_bet[n / 1000];
508 9 : p++;
509 :
510 9 : if (CAL_JEWISH_ADD_ALAFIM_GERESH & fl) {
511 4 : *p = '\'';
512 4 : p++;
513 : }
514 9 : if (CAL_JEWISH_ADD_ALAFIM & fl) {
515 4 : strcpy(p, " אלפים ");
516 4 : p += 7;
517 : }
518 :
519 9 : endofalafim = p;
520 9 : n = n % 1000;
521 : }
522 :
523 : /* tav-tav (tav=400) case */
524 45 : while (n >= 400) {
525 9 : *p = alef_bet[22];
526 9 : p++;
527 9 : n -= 400;
528 : }
529 :
530 : /* meot (hundreads) case */
531 18 : if (n >= 100) {
532 9 : *p = alef_bet[18 + n / 100];
533 9 : p++;
534 9 : n = n % 100;
535 : }
536 :
537 : /* tet-vav & tet-zain case (special case for 15 and 16) */
538 18 : if (n == 15 || n == 16) {
539 0 : *p = alef_bet[9];
540 0 : p++;
541 0 : *p = alef_bet[n - 9];
542 0 : p++;
543 : } else {
544 : /* asarot (tens) case */
545 18 : if (n >= 10) {
546 14 : *p = alef_bet[9 + n / 10];
547 14 : p++;
548 14 : n = n % 10;
549 : }
550 :
551 : /* yehidot (ones) case */
552 18 : if (n > 0) {
553 18 : *p = alef_bet[n];
554 18 : p++;
555 : }
556 : }
557 :
558 18 : if (CAL_JEWISH_ADD_GERESHAYIM & fl) {
559 10 : switch (p - endofalafim) {
560 : case 0:
561 0 : break;
562 : case 1:
563 4 : *p = '\'';
564 4 : p++;
565 4 : break;
566 : default:
567 6 : *(p) = *(p - 1);
568 6 : *(p - 1) = '"';
569 6 : p++;
570 : }
571 : }
572 :
573 18 : *p = '\0';
574 18 : *ret = estrndup(old, (p - old) + 1);
575 18 : p = *ret;
576 18 : return p;
577 : }
578 : /* }}} */
579 :
580 : /* {{{ proto string jdtojewish(int juliandaycount [, bool hebrew [, int fl]])
581 : Converts a julian day count to a jewish calendar date */
582 : PHP_FUNCTION(jdtojewish)
583 10 : {
584 10 : long julday, fl = 0;
585 10 : zend_bool heb = 0;
586 : int year, month, day;
587 : char date[16], hebdate[32];
588 : char *dayp, *yearp;
589 :
590 10 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|bl", &julday, &heb, &fl) == FAILURE) {
591 0 : RETURN_FALSE;
592 : }
593 :
594 10 : SdnToJewish(julday, &year, &month, &day);
595 10 : if (!heb) {
596 1 : snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
597 1 : RETURN_STRING(date, 1);
598 : } else {
599 9 : if (year <= 0 || year > 9999) {
600 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Year out of range (0-9999).");
601 0 : RETURN_FALSE;
602 : }
603 :
604 9 : snprintf(hebdate, sizeof(hebdate), "%s %s %s", heb_number_to_chars(day, fl, &dayp), JewishMonthHebName[month], heb_number_to_chars(year, fl, &yearp));
605 :
606 9 : if (dayp) {
607 9 : efree(dayp);
608 : }
609 9 : if (yearp) {
610 9 : efree(yearp);
611 : }
612 :
613 9 : RETURN_STRING(hebdate, 1);
614 :
615 : }
616 : }
617 : /* }}} */
618 :
619 : /* {{{ proto int jewishtojd(int month, int day, int year)
620 : Converts a jewish calendar date to a julian day count */
621 : PHP_FUNCTION(jewishtojd)
622 4 : {
623 : long year, month, day;
624 :
625 4 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
626 0 : RETURN_FALSE;
627 : }
628 :
629 4 : RETURN_LONG(JewishToSdn(year, month, day));
630 : }
631 : /* }}} */
632 :
633 : /* {{{ proto string jdtofrench(int juliandaycount)
634 : Converts a julian day count to a french republic calendar date */
635 : PHP_FUNCTION(jdtofrench)
636 6 : {
637 : long julday;
638 : int year, month, day;
639 : char date[16];
640 :
641 6 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
642 0 : RETURN_FALSE;
643 : }
644 :
645 6 : SdnToFrench(julday, &year, &month, &day);
646 6 : snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
647 :
648 6 : RETURN_STRING(date, 1);
649 : }
650 : /* }}} */
651 :
652 : /* {{{ proto int frenchtojd(int month, int day, int year)
653 : Converts a french republic calendar date to julian day count */
654 : PHP_FUNCTION(frenchtojd)
655 4 : {
656 : long year, month, day;
657 :
658 4 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
659 0 : RETURN_FALSE;
660 : }
661 :
662 4 : RETURN_LONG(FrenchToSdn(year, month, day));
663 : }
664 : /* }}} */
665 :
666 : /* {{{ proto mixed jddayofweek(int juliandaycount [, int mode])
667 : Returns name or number of day of week from julian day count */
668 : PHP_FUNCTION(jddayofweek)
669 96 : {
670 96 : long julday, mode = CAL_DOW_DAYNO;
671 : int day;
672 : char *daynamel, *daynames;
673 :
674 96 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &julday, &mode) == FAILURE) {
675 0 : RETURN_FALSE;
676 : }
677 :
678 96 : day = DayOfWeek(julday);
679 96 : daynamel = DayNameLong[day];
680 96 : daynames = DayNameShort[day];
681 :
682 96 : switch (mode) {
683 : case CAL_DOW_SHORT:
684 32 : RETURN_STRING(daynamel, 1);
685 : break;
686 : case CAL_DOW_LONG:
687 32 : RETURN_STRING(daynames, 1);
688 : break;
689 : case CAL_DOW_DAYNO:
690 : default:
691 32 : RETURN_LONG(day);
692 : break;
693 : }
694 : }
695 : /* }}} */
696 :
697 : /* {{{ proto string jdmonthname(int juliandaycount, int mode)
698 : Returns name of month for julian day count */
699 : PHP_FUNCTION(jdmonthname)
700 303 : {
701 : long julday, mode;
702 303 : char *monthname = NULL;
703 : int month, day, year;
704 :
705 303 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &julday, &mode) == FAILURE) {
706 6 : RETURN_FALSE;
707 : }
708 :
709 297 : switch (mode) {
710 : case CAL_MONTH_GREGORIAN_LONG: /* gregorian or julian month */
711 43 : SdnToGregorian(julday, &year, &month, &day);
712 43 : monthname = MonthNameLong[month];
713 43 : break;
714 : case CAL_MONTH_JULIAN_SHORT: /* gregorian or julian month */
715 43 : SdnToJulian(julday, &year, &month, &day);
716 43 : monthname = MonthNameShort[month];
717 43 : break;
718 : case CAL_MONTH_JULIAN_LONG: /* gregorian or julian month */
719 43 : SdnToJulian(julday, &year, &month, &day);
720 43 : monthname = MonthNameLong[month];
721 43 : break;
722 : case CAL_MONTH_JEWISH: /* jewish month */
723 43 : SdnToJewish(julday, &year, &month, &day);
724 43 : monthname = JewishMonthName[month];
725 43 : break;
726 : case CAL_MONTH_FRENCH: /* french month */
727 43 : SdnToFrench(julday, &year, &month, &day);
728 43 : monthname = FrenchMonthName[month];
729 43 : break;
730 : default: /* default gregorian */
731 : case CAL_MONTH_GREGORIAN_SHORT: /* gregorian or julian month */
732 82 : SdnToGregorian(julday, &year, &month, &day);
733 82 : monthname = MonthNameShort[month];
734 : break;
735 : }
736 :
737 297 : RETURN_STRING(monthname, 1);
738 : }
739 : /* }}} */
740 :
741 : /*
742 : * Local variables:
743 : * tab-width: 4
744 : * c-basic-offset: 4
745 : * End:
746 : * vim600: sw=4 ts=4 fdm=marker
747 : * vim<600: sw=4 ts=4
748 : */
|