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