Annotation of embedaddon/php/ext/calendar/calendar.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>