Back to index

php5  5.3.10
calendar.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Shane Caraveo             <shane@caraveo.com>               | 
00016    |          Colin Viebrock            <colin@easydns.com>               |
00017    |          Hartmut Holzgraefe        <hholzgra@php.net>                |
00018    |          Wez Furlong               <wez@thebrainroom.com>            |
00019    +----------------------------------------------------------------------+
00020  */
00021 /* $Id: calendar.c 321634 2012-01-01 13:15:04Z felipe $ */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026 
00027 #ifdef PHP_WIN32
00028 #define _WINNLS_
00029 #endif
00030 
00031 #include "php.h"
00032 #include "ext/standard/info.h"
00033 #include "php_calendar.h"
00034 #include "sdncal.h"
00035 
00036 #include <stdio.h>
00037 
00038 /* {{{ arginfo */
00039 ZEND_BEGIN_ARG_INFO_EX(arginfo_unixtojd, 0, 0, 0)
00040        ZEND_ARG_INFO(0, timestamp)
00041 ZEND_END_ARG_INFO()
00042 
00043 ZEND_BEGIN_ARG_INFO(arginfo_jdtounix, 0)
00044        ZEND_ARG_INFO(0, jday)
00045 ZEND_END_ARG_INFO()
00046 
00047 ZEND_BEGIN_ARG_INFO_EX(arginfo_cal_info, 0, 0, 0)
00048        ZEND_ARG_INFO(0, calendar)
00049 ZEND_END_ARG_INFO()
00050 
00051 ZEND_BEGIN_ARG_INFO(arginfo_cal_days_in_month, 0)
00052        ZEND_ARG_INFO(0, calendar)
00053        ZEND_ARG_INFO(0, month)
00054        ZEND_ARG_INFO(0, year)
00055 ZEND_END_ARG_INFO()
00056 
00057 ZEND_BEGIN_ARG_INFO(arginfo_cal_to_jd, 0)
00058        ZEND_ARG_INFO(0, calendar)
00059        ZEND_ARG_INFO(0, month)
00060        ZEND_ARG_INFO(0, day)
00061        ZEND_ARG_INFO(0, year)
00062 ZEND_END_ARG_INFO()
00063 
00064 ZEND_BEGIN_ARG_INFO(arginfo_cal_from_jd, 0)
00065        ZEND_ARG_INFO(0, jd)
00066        ZEND_ARG_INFO(0, calendar)
00067 ZEND_END_ARG_INFO()
00068 
00069 ZEND_BEGIN_ARG_INFO(arginfo_jdtogregorian, 0)
00070        ZEND_ARG_INFO(0, juliandaycount)
00071 ZEND_END_ARG_INFO()
00072 
00073 ZEND_BEGIN_ARG_INFO(arginfo_gregoriantojd, 0)
00074        ZEND_ARG_INFO(0, month)
00075        ZEND_ARG_INFO(0, day)
00076        ZEND_ARG_INFO(0, year)
00077 ZEND_END_ARG_INFO()
00078 
00079 ZEND_BEGIN_ARG_INFO(arginfo_jdtojulian, 0)
00080        ZEND_ARG_INFO(0, juliandaycount)
00081 ZEND_END_ARG_INFO()
00082 
00083 ZEND_BEGIN_ARG_INFO(arginfo_juliantojd, 0)
00084        ZEND_ARG_INFO(0, month)
00085        ZEND_ARG_INFO(0, day)
00086        ZEND_ARG_INFO(0, year)
00087 ZEND_END_ARG_INFO()
00088 
00089 ZEND_BEGIN_ARG_INFO_EX(arginfo_jdtojewish, 0, 0, 1)
00090        ZEND_ARG_INFO(0, juliandaycount)
00091        ZEND_ARG_INFO(0, hebrew)
00092        ZEND_ARG_INFO(0, fl)
00093 ZEND_END_ARG_INFO()
00094 
00095 ZEND_BEGIN_ARG_INFO(arginfo_jewishtojd, 0)
00096        ZEND_ARG_INFO(0, month)
00097        ZEND_ARG_INFO(0, day)
00098        ZEND_ARG_INFO(0, year)
00099 ZEND_END_ARG_INFO()
00100 
00101 ZEND_BEGIN_ARG_INFO(arginfo_jdtofrench, 0)
00102        ZEND_ARG_INFO(0, juliandaycount)
00103 ZEND_END_ARG_INFO()
00104 
00105 ZEND_BEGIN_ARG_INFO(arginfo_frenchtojd, 0)
00106        ZEND_ARG_INFO(0, month)
00107        ZEND_ARG_INFO(0, day)
00108        ZEND_ARG_INFO(0, year)
00109 ZEND_END_ARG_INFO()
00110 
00111 ZEND_BEGIN_ARG_INFO_EX(arginfo_jddayofweek, 0, 0, 1)
00112        ZEND_ARG_INFO(0, juliandaycount)
00113        ZEND_ARG_INFO(0, mode)
00114 ZEND_END_ARG_INFO()
00115 
00116 ZEND_BEGIN_ARG_INFO(arginfo_jdmonthname, 0)
00117        ZEND_ARG_INFO(0, juliandaycount)
00118        ZEND_ARG_INFO(0, mode)
00119 ZEND_END_ARG_INFO()
00120 
00121 ZEND_BEGIN_ARG_INFO_EX(arginfo_easter_date, 0, 0, 0)
00122        ZEND_ARG_INFO(0, year)
00123 ZEND_END_ARG_INFO()
00124 
00125 ZEND_BEGIN_ARG_INFO_EX(arginfo_easter_days, 0, 0, 0)
00126        ZEND_ARG_INFO(0, year)
00127        ZEND_ARG_INFO(0, method)
00128 ZEND_END_ARG_INFO()
00129 
00130 /* }}} */
00131 
00132 const zend_function_entry calendar_functions[] = {
00133        PHP_FE(jdtogregorian, arginfo_jdtogregorian)
00134        PHP_FE(gregoriantojd, arginfo_gregoriantojd)
00135        PHP_FE(jdtojulian, arginfo_jdtojulian)
00136        PHP_FE(juliantojd, arginfo_juliantojd)
00137        PHP_FE(jdtojewish, arginfo_jdtojewish)
00138        PHP_FE(jewishtojd, arginfo_jewishtojd)
00139        PHP_FE(jdtofrench, arginfo_jdtofrench)
00140        PHP_FE(frenchtojd, arginfo_frenchtojd)
00141        PHP_FE(jddayofweek, arginfo_jddayofweek)
00142        PHP_FE(jdmonthname, arginfo_jdmonthname)
00143        PHP_FE(easter_date, arginfo_easter_date) 
00144        PHP_FE(easter_days, arginfo_easter_days)
00145        PHP_FE(unixtojd, arginfo_unixtojd)
00146        PHP_FE(jdtounix, arginfo_jdtounix)
00147        PHP_FE(cal_to_jd, arginfo_cal_to_jd)
00148        PHP_FE(cal_from_jd, arginfo_cal_from_jd)
00149        PHP_FE(cal_days_in_month, arginfo_cal_days_in_month)
00150        PHP_FE(cal_info, arginfo_cal_info)
00151        PHP_FE_END
00152 };
00153 
00154 
00155 zend_module_entry calendar_module_entry = {
00156        STANDARD_MODULE_HEADER,
00157        "calendar",
00158        calendar_functions,
00159        PHP_MINIT(calendar),
00160        NULL,
00161        NULL,
00162        NULL,
00163        PHP_MINFO(calendar),
00164        NO_VERSION_YET,
00165        STANDARD_MODULE_PROPERTIES,
00166 };
00167 
00168 #ifdef COMPILE_DL_CALENDAR
00169 ZEND_GET_MODULE(calendar)
00170 #endif
00171 
00172 /* this order must match the conversion table below */
00173 enum cal_name_type_t {
00174        CAL_GREGORIAN = 0,
00175        CAL_JULIAN,
00176        CAL_JEWISH,
00177        CAL_FRENCH,
00178        CAL_NUM_CALS
00179 };
00180 
00181 typedef long int (*cal_to_jd_func_t) (int month, int day, int year);
00182 typedef void (*cal_from_jd_func_t) (long int jd, int *year, int *month, int *day);
00183 typedef char *(*cal_as_string_func_t) (int year, int month, int day);
00184 
00185 struct cal_entry_t {
00186        char *name;
00187        char *symbol;
00188        cal_to_jd_func_t to_jd;
00189        cal_from_jd_func_t from_jd;
00190        int num_months;
00191        int max_days_in_month;
00192        char **month_name_short;
00193        char **month_name_long;
00194 };
00195 
00196 static struct cal_entry_t cal_conversion_table[CAL_NUM_CALS] = {
00197        {"Gregorian", "CAL_GREGORIAN", GregorianToSdn, SdnToGregorian, 12, 31,
00198         MonthNameShort, MonthNameLong},
00199        {"Julian", "CAL_JULIAN", JulianToSdn, SdnToJulian, 12, 31,
00200         MonthNameShort, MonthNameLong},
00201        {"Jewish", "CAL_JEWISH", JewishToSdn, SdnToJewish, 13, 30,
00202         JewishMonthName, JewishMonthName},
00203        {"French", "CAL_FRENCH", FrenchToSdn, SdnToFrench, 13, 30,
00204         FrenchMonthName, FrenchMonthName}
00205 };
00206 
00207 /* For jddayofweek */
00208 enum { CAL_DOW_DAYNO, CAL_DOW_SHORT, CAL_DOW_LONG };
00209 
00210 /* For jdmonthname */
00211 enum { CAL_MONTH_GREGORIAN_SHORT, CAL_MONTH_GREGORIAN_LONG,
00212        CAL_MONTH_JULIAN_SHORT, CAL_MONTH_JULIAN_LONG, CAL_MONTH_JEWISH,
00213        CAL_MONTH_FRENCH
00214 };
00215 
00216 /* for heb_number_to_chars */
00217 static char alef_bet[25] = "0אבגדהוזחטיכלמנסעפצקרשת";
00218 
00219 #define CAL_JEWISH_ADD_ALAFIM_GERESH 0x2
00220 #define CAL_JEWISH_ADD_ALAFIM 0x4
00221 #define CAL_JEWISH_ADD_GERESHAYIM 0x8
00222 
00223 PHP_MINIT_FUNCTION(calendar)
00224 {
00225        REGISTER_LONG_CONSTANT("CAL_GREGORIAN", CAL_GREGORIAN, CONST_CS | CONST_PERSISTENT);
00226        REGISTER_LONG_CONSTANT("CAL_JULIAN", CAL_JULIAN, CONST_CS | CONST_PERSISTENT);
00227        REGISTER_LONG_CONSTANT("CAL_JEWISH", CAL_JEWISH, CONST_CS | CONST_PERSISTENT);
00228        REGISTER_LONG_CONSTANT("CAL_FRENCH", CAL_FRENCH, CONST_CS | CONST_PERSISTENT);
00229        REGISTER_LONG_CONSTANT("CAL_NUM_CALS", CAL_NUM_CALS, CONST_CS | CONST_PERSISTENT);
00230 /* constants for jddayofweek */
00231        REGISTER_LONG_CONSTANT("CAL_DOW_DAYNO", CAL_DOW_DAYNO, CONST_CS | CONST_PERSISTENT);
00232        REGISTER_LONG_CONSTANT("CAL_DOW_SHORT", CAL_DOW_SHORT, CONST_CS | CONST_PERSISTENT);
00233        REGISTER_LONG_CONSTANT("CAL_DOW_LONG", CAL_DOW_LONG, CONST_CS | CONST_PERSISTENT);
00234 /* constants for jdmonthname */
00235        REGISTER_LONG_CONSTANT("CAL_MONTH_GREGORIAN_SHORT", CAL_MONTH_GREGORIAN_SHORT, CONST_CS | CONST_PERSISTENT);
00236        REGISTER_LONG_CONSTANT("CAL_MONTH_GREGORIAN_LONG", CAL_MONTH_GREGORIAN_LONG, CONST_CS | CONST_PERSISTENT);
00237        REGISTER_LONG_CONSTANT("CAL_MONTH_JULIAN_SHORT", CAL_MONTH_JULIAN_SHORT, CONST_CS | CONST_PERSISTENT);
00238        REGISTER_LONG_CONSTANT("CAL_MONTH_JULIAN_LONG", CAL_MONTH_JULIAN_LONG, CONST_CS | CONST_PERSISTENT);
00239        REGISTER_LONG_CONSTANT("CAL_MONTH_JEWISH", CAL_MONTH_JEWISH, CONST_CS | CONST_PERSISTENT);
00240        REGISTER_LONG_CONSTANT("CAL_MONTH_FRENCH", CAL_MONTH_FRENCH, CONST_CS | CONST_PERSISTENT);
00241 /* constants for easter calculation */
00242        REGISTER_LONG_CONSTANT("CAL_EASTER_DEFAULT", CAL_EASTER_DEFAULT, CONST_CS | CONST_PERSISTENT);
00243        REGISTER_LONG_CONSTANT("CAL_EASTER_ROMAN", CAL_EASTER_ROMAN, CONST_CS | CONST_PERSISTENT);
00244        REGISTER_LONG_CONSTANT("CAL_EASTER_ALWAYS_GREGORIAN", CAL_EASTER_ALWAYS_GREGORIAN, CONST_CS | CONST_PERSISTENT);
00245        REGISTER_LONG_CONSTANT("CAL_EASTER_ALWAYS_JULIAN", CAL_EASTER_ALWAYS_JULIAN, CONST_CS | CONST_PERSISTENT);
00246 /* constants for Jewish date formatting */
00247        REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_ALAFIM_GERESH", CAL_JEWISH_ADD_ALAFIM_GERESH, CONST_CS | CONST_PERSISTENT);
00248        REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_ALAFIM", CAL_JEWISH_ADD_ALAFIM, CONST_CS | CONST_PERSISTENT);
00249        REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_GERESHAYIM", CAL_JEWISH_ADD_GERESHAYIM, CONST_CS | CONST_PERSISTENT);
00250        return SUCCESS;
00251 }
00252 
00253 PHP_MINFO_FUNCTION(calendar)
00254 {
00255        php_info_print_table_start();
00256        php_info_print_table_row(2, "Calendar support", "enabled");
00257        php_info_print_table_end();
00258 }
00259 
00260 static void _php_cal_info(int cal, zval **ret)
00261 {
00262        zval *months, *smonths;
00263        int i;
00264        struct cal_entry_t *calendar;
00265 
00266        calendar = &cal_conversion_table[cal];
00267        array_init(*ret);
00268 
00269        MAKE_STD_ZVAL(months);
00270        MAKE_STD_ZVAL(smonths);
00271        array_init(months);
00272        array_init(smonths);
00273 
00274        for (i = 1; i <= calendar->num_months; i++) {
00275               add_index_string(months, i, calendar->month_name_long[i], 1);
00276               add_index_string(smonths, i, calendar->month_name_short[i], 1);
00277        }
00278        add_assoc_zval(*ret, "months", months);
00279        add_assoc_zval(*ret, "abbrevmonths", smonths);
00280        add_assoc_long(*ret, "maxdaysinmonth", calendar->max_days_in_month);
00281        add_assoc_string(*ret, "calname", calendar->name, 1);
00282        add_assoc_string(*ret, "calsymbol", calendar->symbol, 1);
00283        
00284 }
00285 
00286 /* {{{ proto array cal_info([int calendar])
00287    Returns information about a particular calendar */
00288 PHP_FUNCTION(cal_info)
00289 {
00290        long cal = -1;
00291        
00292 
00293        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &cal) == FAILURE) {
00294               RETURN_FALSE;
00295        }
00296 
00297        if (cal == -1) {
00298               int i;
00299               zval *val;
00300 
00301               array_init(return_value);
00302 
00303               for (i = 0; i < CAL_NUM_CALS; i++) {
00304                      MAKE_STD_ZVAL(val);
00305                      _php_cal_info(i, &val);
00306                      add_index_zval(return_value, i, val);
00307               }
00308               return;
00309        }
00310 
00311 
00312        if (cal != -1 && (cal < 0 || cal >= CAL_NUM_CALS)) {
00313               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
00314               RETURN_FALSE;
00315        }
00316 
00317        _php_cal_info(cal, &return_value);
00318 
00319 }
00320 /* }}} */
00321 
00322 /* {{{ proto int cal_days_in_month(int calendar, int month, int year)
00323    Returns the number of days in a month for a given year and calendar */
00324 PHP_FUNCTION(cal_days_in_month)
00325 {
00326        long cal, month, year;
00327        struct cal_entry_t *calendar;
00328        long sdn_start, sdn_next;
00329 
00330        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &cal, &month, &year) == FAILURE) {
00331               RETURN_FALSE;
00332        }
00333 
00334        if (cal < 0 || cal >= CAL_NUM_CALS) {
00335               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
00336               RETURN_FALSE;
00337        }
00338 
00339        calendar = &cal_conversion_table[cal];
00340 
00341        sdn_start = calendar->to_jd(year, month, 1);
00342 
00343        if (sdn_start == 0) {
00344               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid date.");
00345               RETURN_FALSE;
00346        }
00347 
00348        sdn_next = calendar->to_jd(year, 1 + month, 1);
00349 
00350        if (sdn_next == 0) {
00351               /* If the next month is invalid, then we need to try the first month of
00352                * the next year, bearing in mind that the next year after 1 BCE is
00353                * actually 1 AD and not 0. */
00354               if (year == -1) {
00355                      sdn_next = calendar->to_jd(1, 1, 1);
00356               }
00357               else {
00358                      sdn_next = calendar->to_jd(year + 1, 1, 1);
00359               }
00360        }
00361 
00362        RETURN_LONG(sdn_next - sdn_start);
00363 }
00364 /* }}} */
00365 
00366 /* {{{ proto int cal_to_jd(int calendar, int month, int day, int year)
00367    Converts from a supported calendar to Julian Day Count */
00368 PHP_FUNCTION(cal_to_jd)
00369 {
00370        long cal, month, day, year;
00371 
00372        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &cal, &month, &day, &year) != SUCCESS) {
00373               RETURN_FALSE;
00374        }
00375 
00376        if (cal < 0 || cal >= CAL_NUM_CALS) {
00377               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
00378               RETURN_FALSE;
00379        }
00380 
00381        RETURN_LONG(cal_conversion_table[cal].to_jd(year, month, day));
00382 }
00383 /* }}} */
00384 
00385 /* {{{ proto array cal_from_jd(int jd, int calendar)
00386    Converts from Julian Day Count to a supported calendar and return extended information */
00387 PHP_FUNCTION(cal_from_jd)
00388 {
00389        long jd, cal;
00390        int month, day, year, dow;
00391        char date[16];
00392        struct cal_entry_t *calendar;
00393 
00394        if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "ll", &jd, &cal) == FAILURE) {
00395               RETURN_FALSE;
00396        }
00397 
00398        if (cal < 0 || cal >= CAL_NUM_CALS) {
00399               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld", cal);
00400               RETURN_FALSE;
00401        }
00402        calendar = &cal_conversion_table[cal];
00403 
00404        array_init(return_value);
00405 
00406        calendar->from_jd(jd, &year, &month, &day);
00407 
00408        snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
00409        add_assoc_string(return_value, "date", date, 1);
00410 
00411        add_assoc_long(return_value, "month", month);
00412        add_assoc_long(return_value, "day", day);
00413        add_assoc_long(return_value, "year", year);
00414 
00415 /* day of week */
00416        dow = DayOfWeek(jd);
00417        add_assoc_long(return_value, "dow", dow);
00418        add_assoc_string(return_value, "abbrevdayname", DayNameShort[dow], 1);
00419        add_assoc_string(return_value, "dayname", DayNameLong[dow], 1);
00420 /* month name */
00421        add_assoc_string(return_value, "abbrevmonth", calendar->month_name_short[month], 1);
00422        add_assoc_string(return_value, "monthname", calendar->month_name_long[month], 1);
00423 }
00424 /* }}} */
00425 
00426 /* {{{ proto string jdtogregorian(int juliandaycount)
00427    Converts a julian day count to a gregorian calendar date */
00428 PHP_FUNCTION(jdtogregorian)
00429 {
00430        long julday;
00431        int year, month, day;
00432        char date[16];
00433 
00434        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
00435               RETURN_FALSE;
00436        }
00437 
00438        SdnToGregorian(julday, &year, &month, &day);
00439        snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
00440 
00441        RETURN_STRING(date, 1);
00442 }
00443 /* }}} */
00444 
00445 /* {{{ proto int gregoriantojd(int month, int day, int year)
00446    Converts a gregorian calendar date to julian day count */
00447 PHP_FUNCTION(gregoriantojd)
00448 {
00449        long year, month, day;
00450 
00451        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
00452               RETURN_FALSE;
00453        }
00454 
00455        RETURN_LONG(GregorianToSdn(year, month, day));
00456 }
00457 /* }}} */
00458 
00459 /* {{{ proto string jdtojulian(int juliandaycount)
00460    Convert a julian day count to a julian calendar date */
00461 PHP_FUNCTION(jdtojulian)
00462 {
00463        long julday;
00464        int year, month, day;
00465        char date[16];
00466 
00467        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
00468               RETURN_FALSE;
00469        }
00470 
00471        SdnToJulian(julday, &year, &month, &day);
00472        snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
00473 
00474        RETURN_STRING(date, 1);
00475 }
00476 /* }}} */
00477 
00478 /* {{{ proto int juliantojd(int month, int day, int year)
00479    Converts a julian calendar date to julian day count */
00480 PHP_FUNCTION(juliantojd)
00481 {
00482        long year, month, day;
00483 
00484        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
00485               RETURN_FALSE;
00486        }
00487 
00488        RETURN_LONG(JulianToSdn(year, month, day));
00489 }
00490 /* }}} */
00491 
00492 /* {{{ heb_number_to_chars*/
00493 /*
00494 caution: the Hebrew format produces non unique result.
00495 for example both: year '5' and year '5000' produce 'ה'.
00496 use the numeric one for calculations. 
00497  */
00498 static char *heb_number_to_chars(int n, int fl, char **ret)
00499 {
00500        char *p, old[18], *endofalafim;
00501 
00502        p = endofalafim = old;
00503 /* 
00504    prevents the option breaking the jewish beliefs, and some other 
00505    critical resources ;)
00506  */
00507        if (n > 9999 || n < 1) {
00508               *ret = NULL;
00509               return NULL;
00510        }      
00511 
00512 /* alafim (thousands) case */
00513        if (n / 1000) {
00514               *p = alef_bet[n / 1000];
00515               p++;
00516 
00517               if (CAL_JEWISH_ADD_ALAFIM_GERESH & fl) {
00518                      *p = '\'';
00519                      p++;
00520               }
00521               if (CAL_JEWISH_ADD_ALAFIM & fl) {
00522                      strcpy(p, " אלפים ");
00523                      p += 7;
00524               }
00525 
00526               endofalafim = p;
00527               n = n % 1000;
00528        }
00529 
00530 /* tav-tav (tav=400) case */
00531        while (n >= 400) {
00532               *p = alef_bet[22];
00533               p++;
00534               n -= 400;
00535        }
00536 
00537 /* meot (hundreads) case */
00538        if (n >= 100) {
00539               *p = alef_bet[18 + n / 100];
00540               p++;
00541               n = n % 100;
00542        }
00543 
00544 /* tet-vav & tet-zain case (special case for 15 and 16) */
00545        if (n == 15 || n == 16) {
00546               *p = alef_bet[9];
00547               p++;
00548               *p = alef_bet[n - 9];
00549               p++;
00550        } else {
00551 /* asarot (tens) case */
00552               if (n >= 10) {
00553                      *p = alef_bet[9 + n / 10];
00554                      p++;
00555                      n = n % 10;
00556               }
00557 
00558 /* yehidot (ones) case */
00559               if (n > 0) {
00560                      *p = alef_bet[n];
00561                      p++;
00562               }
00563        }
00564 
00565        if (CAL_JEWISH_ADD_GERESHAYIM & fl) {
00566               switch (p - endofalafim) {
00567               case 0:
00568                      break;
00569               case 1:
00570                      *p = '\'';
00571                      p++;
00572                      break;
00573               default:
00574                      *(p) = *(p - 1);
00575                      *(p - 1) = '"';
00576                      p++;
00577               }
00578        }
00579 
00580        *p = '\0';
00581        *ret = estrndup(old, (p - old) + 1);
00582        p = *ret;
00583        return p;
00584 }
00585 /* }}} */
00586 
00587 /* {{{ proto string jdtojewish(int juliandaycount [, bool hebrew [, int fl]])
00588    Converts a julian day count to a jewish calendar date */
00589 PHP_FUNCTION(jdtojewish)
00590 {
00591        long julday, fl = 0;
00592        zend_bool heb   = 0;
00593        int year, month, day;
00594        char date[16], hebdate[32];
00595        char *dayp, *yearp;
00596 
00597        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|bl", &julday, &heb, &fl) == FAILURE) {
00598               RETURN_FALSE;
00599        }
00600 
00601        SdnToJewish(julday, &year, &month, &day);
00602        if (!heb) {
00603               snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
00604               RETURN_STRING(date, 1);
00605        } else {
00606               if (year <= 0 || year > 9999) {
00607                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Year out of range (0-9999).");
00608                      RETURN_FALSE;
00609               }
00610 
00611               snprintf(hebdate, sizeof(hebdate), "%s %s %s", heb_number_to_chars(day, fl, &dayp), JewishMonthHebName[month], heb_number_to_chars(year, fl, &yearp));
00612 
00613               if (dayp) {
00614                      efree(dayp);
00615               }
00616               if (yearp) {
00617                      efree(yearp);
00618               }
00619 
00620               RETURN_STRING(hebdate, 1);
00621 
00622        }
00623 }
00624 /* }}} */
00625 
00626 /* {{{ proto int jewishtojd(int month, int day, int year)
00627    Converts a jewish calendar date to a julian day count */
00628 PHP_FUNCTION(jewishtojd)
00629 {
00630        long year, month, day;
00631 
00632        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
00633               RETURN_FALSE;
00634        }
00635 
00636        RETURN_LONG(JewishToSdn(year, month, day));
00637 }
00638 /* }}} */
00639 
00640 /* {{{ proto string jdtofrench(int juliandaycount)
00641    Converts a julian day count to a french republic calendar date */
00642 PHP_FUNCTION(jdtofrench)
00643 {
00644        long julday;
00645        int year, month, day;
00646        char date[16];
00647 
00648        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
00649               RETURN_FALSE;
00650        }
00651 
00652        SdnToFrench(julday, &year, &month, &day);
00653        snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
00654 
00655        RETURN_STRING(date, 1);
00656 }
00657 /* }}} */
00658 
00659 /* {{{ proto int frenchtojd(int month, int day, int year)
00660    Converts a french republic calendar date to julian day count */
00661 PHP_FUNCTION(frenchtojd)
00662 {
00663        long year, month, day;
00664 
00665        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
00666               RETURN_FALSE;
00667        }
00668 
00669        RETURN_LONG(FrenchToSdn(year, month, day));
00670 }
00671 /* }}} */
00672 
00673 /* {{{ proto mixed jddayofweek(int juliandaycount [, int mode])
00674    Returns name or number of day of week from julian day count */
00675 PHP_FUNCTION(jddayofweek)
00676 {
00677        long julday, mode = CAL_DOW_DAYNO;
00678        int day;
00679        char *daynamel, *daynames;
00680 
00681        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &julday, &mode) == FAILURE) {
00682               RETURN_FALSE;
00683        }
00684 
00685        day = DayOfWeek(julday);
00686        daynamel = DayNameLong[day];
00687        daynames = DayNameShort[day];
00688 
00689        switch (mode) {
00690        case CAL_DOW_SHORT:
00691               RETURN_STRING(daynamel, 1);
00692               break;
00693        case CAL_DOW_LONG:
00694               RETURN_STRING(daynames, 1);
00695               break;
00696        case CAL_DOW_DAYNO:
00697        default:
00698               RETURN_LONG(day);
00699               break;
00700        }
00701 }
00702 /* }}} */
00703 
00704 /* {{{ proto string jdmonthname(int juliandaycount, int mode)
00705    Returns name of month for julian day count */
00706 PHP_FUNCTION(jdmonthname)
00707 {
00708        long julday, mode;
00709        char *monthname = NULL;
00710        int month, day, year;
00711 
00712        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &julday, &mode) == FAILURE) {
00713               RETURN_FALSE;
00714        }
00715 
00716        switch (mode) {
00717        case CAL_MONTH_GREGORIAN_LONG:     /* gregorian or julian month */
00718               SdnToGregorian(julday, &year, &month, &day);
00719               monthname = MonthNameLong[month];
00720               break;
00721        case CAL_MONTH_JULIAN_SHORT:       /* gregorian or julian month */
00722               SdnToJulian(julday, &year, &month, &day);
00723               monthname = MonthNameShort[month];
00724               break;
00725        case CAL_MONTH_JULIAN_LONG: /* gregorian or julian month */
00726               SdnToJulian(julday, &year, &month, &day);
00727               monthname = MonthNameLong[month];
00728               break;
00729        case CAL_MONTH_JEWISH:             /* jewish month */
00730               SdnToJewish(julday, &year, &month, &day);
00731               monthname = JewishMonthName[month];
00732               break;
00733        case CAL_MONTH_FRENCH:             /* french month */
00734               SdnToFrench(julday, &year, &month, &day);
00735               monthname = FrenchMonthName[month];
00736               break;
00737        default:                                  /* default gregorian */
00738        case CAL_MONTH_GREGORIAN_SHORT:    /* gregorian or julian month */
00739               SdnToGregorian(julday, &year, &month, &day);
00740               monthname = MonthNameShort[month];
00741               break;
00742        }
00743 
00744        RETURN_STRING(monthname, 1);
00745 }
00746 /* }}} */
00747 
00748 /*
00749  * Local variables:
00750  * tab-width: 4
00751  * c-basic-offset: 4
00752  * End:
00753  * vim600: sw=4 ts=4 fdm=marker
00754  * vim<600: sw=4 ts=4
00755  */