From a07a26888e1db18be729f10bafe6cf4bbb65ce5f Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Wed, 4 Jul 2001 10:12:45 +0000 Subject: [PATCH] Added a couple of new functions to "modularize" working with calendars. Added a few constants for the existing functions, and tidied them up a bit. --- ext/calendar/CREDITS | 2 + ext/calendar/calendar.c | 284 ++++++++++++++++++++++++++++++------ ext/calendar/php_calendar.h | 5 +- 3 files changed, 244 insertions(+), 47 deletions(-) diff --git a/ext/calendar/CREDITS b/ext/calendar/CREDITS index e69de29bb2..a2904bd8b2 100644 --- a/ext/calendar/CREDITS +++ b/ext/calendar/CREDITS @@ -0,0 +1,2 @@ +Calendar +Shane Caraveo, Colin Viebrock, Hartmut Holzgraefe, Wez Furlong diff --git a/ext/calendar/calendar.c b/ext/calendar/calendar.c index 12ae1aae67..7c06d393fb 100644 --- a/ext/calendar/calendar.c +++ b/ext/calendar/calendar.c @@ -15,9 +15,10 @@ | Authors: Shane Caraveo | | Colin Viebrock | | Hartmut Holzgraefe | + | Wez Furlong | +----------------------------------------------------------------------+ */ -/* $Id: */ +/* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -43,6 +44,10 @@ function_entry calendar_functions[] = { PHP_FE(easter_days, NULL) PHP_FE(unixtojd, NULL) PHP_FE(jdtounix, NULL) + PHP_FE(cal_to_jd, NULL) + PHP_FE(cal_from_jd, NULL) + PHP_FE(cal_days_in_month, NULL) + PHP_FE(cal_info, NULL) {NULL, NULL, NULL} }; @@ -50,7 +55,7 @@ function_entry calendar_functions[] = { zend_module_entry calendar_module_entry = { "calendar", calendar_functions, - NULL, /*PHP_MINIT(calendar),*/ + PHP_MINIT(calendar), NULL, NULL, NULL, @@ -62,12 +67,62 @@ zend_module_entry calendar_module_entry = { ZEND_GET_MODULE(calendar) #endif +/* this order must match the conversion table below */ +enum { + CAL_GREGORIAN = 0, + CAL_JULIAN, + CAL_JEWISH, + CAL_FRENCH, + CAL_NUM_CALS +}; +typedef long int (*cal_to_jd_func_t)(int month, int day, int year); +typedef void (*cal_from_jd_func_t)(long int jd, int* year, int* month, int* day); +typedef char* (*cal_as_string_func_t)(int year, int month, int day); + +struct cal_entry_t { + char * name; + char * symbol; + cal_to_jd_func_t to_jd; + cal_from_jd_func_t from_jd; + int num_months; + int max_days_in_month; + char ** month_name_short; + char ** month_name_long; +}; +static struct cal_entry_t cal_conversion_table[CAL_NUM_CALS] = { + { "Gregorian", "CAL_GREGORIAN", GregorianToSdn, SdnToGregorian, 12, 31, MonthNameShort, MonthNameLong }, + { "Julian", "CAL_JULIAN", JulianToSdn, SdnToJulian, 12, 31, MonthNameShort, MonthNameLong }, + { "Jewish", "CAL_JEWISH", JewishToSdn, SdnToJewish, 13, 30, JewishMonthName, JewishMonthName }, + { "French", "CAL_FRENCH", FrenchToSdn, SdnToFrench, 13, 30, FrenchMonthName, FrenchMonthName } +}; + +/* For jddayofweek */ +enum { CAL_DOW_DAYNO, CAL_DOW_SHORT, CAL_DOW_LONG }; +/* For jdmonthname */ +enum { CAL_MONTH_GREGORIAN_SHORT, CAL_MONTH_GREGORIAN_LONG, + CAL_MONTH_JULIAN_SHORT, CAL_MONTH_JULIAN_LONG, CAL_MONTH_JEWISH, + CAL_MONTH_FRENCH }; + PHP_MINIT_FUNCTION(calendar) { - /* - REGISTER_INT_CONSTANT("CAL_EASTER_TO_xxx",0, CONST_CS | CONST_PERSISTENT); - */ - return SUCCESS; + REGISTER_LONG_CONSTANT("CAL_GREGORIAN", CAL_GREGORIAN, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CAL_JULIAN", CAL_JULIAN, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CAL_JEWISH", CAL_JEWISH, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CAL_FRENCH", CAL_FRENCH, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CAL_NUM_CALS", CAL_NUM_CALS, CONST_CS|CONST_PERSISTENT); + /* constants for jddayofweek */ + REGISTER_LONG_CONSTANT("CAL_DOW_DAYNO", CAL_DOW_DAYNO, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CAL_DOW_SHORT", CAL_DOW_SHORT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CAL_DOW_LONG", CAL_DOW_LONG, CONST_CS|CONST_PERSISTENT); + /* constants for jdmonthname */ + REGISTER_LONG_CONSTANT("CAL_MONTH_GREGORIAN_SHORT", CAL_MONTH_GREGORIAN_SHORT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CAL_MONTH_GREGORIAN_LONG", CAL_MONTH_GREGORIAN_LONG, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CAL_MONTH_JULIAN_SHORT", CAL_MONTH_JULIAN_SHORT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CAL_MONTH_JULIAN_LONG", CAL_MONTH_JULIAN_LONG, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CAL_MONTH_JEWISH", CAL_MONTH_JEWISH, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("CAL_MONTH_FRENCH", CAL_MONTH_FRENCH, CONST_CS|CONST_PERSISTENT); + + return SUCCESS; } PHP_MINFO_FUNCTION(calendar) @@ -77,6 +132,152 @@ PHP_MINFO_FUNCTION(calendar) php_info_print_table_end(); } +/* {{{ proto array cal_info(int calendar) + * Return information about a particular calendar */ +PHP_FUNCTION(cal_info) +{ + zval ** cal; + zval * months, *smonths; + int i; + struct cal_entry_t * calendar; + + if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &cal) != SUCCESS) { + WRONG_PARAM_COUNT; + } + convert_to_long_ex(cal); + if (Z_LVAL_PP(cal) < 0 || Z_LVAL_PP(cal) >= CAL_NUM_CALS) { + zend_error(E_WARNING, "%s(): invalid calendar ID %d", get_active_function_name(), Z_LVAL_PP(cal)); + RETURN_FALSE; + } + + calendar = &cal_conversion_table[Z_LVAL_PP(cal)]; + array_init(return_value); + + MAKE_STD_ZVAL(months); + MAKE_STD_ZVAL(smonths); + array_init(months); + array_init(smonths); + + for (i=1; i<= calendar->num_months; i++) { + add_index_string(months, i, calendar->month_name_long[i], 1); + add_index_string(smonths, i, calendar->month_name_short[i], 1); + } + add_assoc_zval(return_value, "months", months); + add_assoc_zval(return_value, "abbrevmonths", smonths); + add_assoc_long(return_value, "maxdaysinmonth", calendar->max_days_in_month); + add_assoc_string(return_value, "calname", calendar->name, 1); + add_assoc_string(return_value, "calsymbol", calendar->symbol, 1); + +} +/* }}} */ + +/* {{{ proto int cal_days_in_month(int calendar, int month, int year) + * Returns the number of days in a month for a given year and calendar */ +PHP_FUNCTION(cal_days_in_month) +{ + zval ** cal, **month, **year; + struct cal_entry_t * calendar; + long sdn_start, sdn_next; + + if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &cal, &month, &year) != SUCCESS) { + WRONG_PARAM_COUNT; + } + + convert_to_long_ex(cal); + convert_to_long_ex(month); + convert_to_long_ex(year); + + if (Z_LVAL_PP(cal) < 0 || Z_LVAL_PP(cal) >= CAL_NUM_CALS) { + zend_error(E_WARNING, "%s(): invalid calendar ID %d", get_active_function_name(), Z_LVAL_PP(cal)); + RETURN_FALSE; + } + + calendar = &cal_conversion_table[Z_LVAL_PP(cal)]; + + sdn_start = calendar->to_jd(Z_LVAL_PP(year), Z_LVAL_PP(month), 1); + + sdn_next = calendar->to_jd(Z_LVAL_PP(year), 1 + Z_LVAL_PP(month), 1); + + if (sdn_next == 0) { + /* if invalid, try first month of the next year... */ + sdn_next = calendar->to_jd(Z_LVAL_PP(year) + 1, 1, 1); + } + + RETURN_LONG(sdn_next - sdn_start); +} +/* }}} */ + +/* {{{ proto int cal_to_jd(int calendar, int month, int day, int year) + * Convert from a supported calendar to Julian Day Count */ +PHP_FUNCTION(cal_to_jd) +{ + zval ** cal, **month, **day, **year; + long jdate; + + if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &cal, &month, &day, &year) != SUCCESS) { + WRONG_PARAM_COUNT; + } + + convert_to_long_ex(cal); + convert_to_long_ex(month); + convert_to_long_ex(day); + convert_to_long_ex(year); + + if (Z_LVAL_PP(cal) < 0 || Z_LVAL_PP(cal) >= CAL_NUM_CALS) { + zend_error(E_WARNING, "%s(): invalid calendar ID %d", get_active_function_name(), Z_LVAL_PP(cal)); + RETURN_FALSE; + } + + jdate = cal_conversion_table[Z_LVAL_PP(cal)].to_jd( + Z_LVAL_PP(year), Z_LVAL_PP(month), Z_LVAL_PP(day)); + RETURN_LONG(jdate); +} +/* }}} */ + +/* {{{ proto array cal_from_jd(int jd, int calendar) + * Convert from Julian Day Count to a supported calendar and return extended information */ +PHP_FUNCTION(cal_from_jd) +{ + zval ** jd, ** cal; + int month, day, year, dow; + char date[16]; + struct cal_entry_t * calendar; + + if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &jd, &cal) != SUCCESS) { + WRONG_PARAM_COUNT; + } + convert_to_long_ex(jd); + convert_to_long_ex(cal); + + if (Z_LVAL_PP(cal) < 0 || Z_LVAL_PP(cal) >= CAL_NUM_CALS) { + zend_error(E_WARNING, "%s(): invalid calendar ID %d", get_active_function_name(), Z_LVAL_PP(cal)); + RETURN_FALSE; + } + calendar = &cal_conversion_table[Z_LVAL_PP(cal)]; + + array_init(return_value); + + calendar->from_jd( + Z_LVAL_PP(jd), + &year, &month, &day); + + sprintf(date, "%i/%i/%i", month, day, year); + add_assoc_string(return_value, "date", date, 1); + + add_assoc_long(return_value, "month", month); + add_assoc_long(return_value, "day", day); + add_assoc_long(return_value, "year", year); + + /* day of week */ + dow = DayOfWeek(Z_LVAL_PP(jd)); + add_assoc_long(return_value, "dow", dow); + add_assoc_string(return_value, "abbrevdayname", DayNameShort[dow], 1); + add_assoc_string(return_value, "dayname", DayNameLong[dow], 1); + /* month name */ + add_assoc_string(return_value, "abbrevmonth", calendar->month_name_short[month], 1); + add_assoc_string(return_value, "monthname", calendar->month_name_long[month], 1); +} +/* }}} */ /* {{{ proto string jdtogregorian(int juliandaycount) Convert a julian day count to a gregorian calendar date */ @@ -139,7 +340,6 @@ PHP_FUNCTION(jdtogregorian) } /* }}} */ - /* {{{ proto int juliantojd(int month, int day, int year) Convert a julian calendar date to julian day count */ PHP_FUNCTION(juliantojd) @@ -161,7 +361,6 @@ PHP_FUNCTION(jdtogregorian) } /* }}} */ - /* {{{ proto string jdtojewish(int juliandaycount) Convert a julian day count to a jewish calendar date */ PHP_FUNCTION(jdtojewish) @@ -183,7 +382,6 @@ PHP_FUNCTION(jdtogregorian) } /* }}} */ - /* {{{ proto int jewishtojd(int month, int day, int year) Convert a jewish calendar date to a julian day count */ PHP_FUNCTION(jewishtojd) @@ -205,7 +403,6 @@ PHP_FUNCTION(jdtogregorian) } /* }}} */ - /* {{{ proto string jdtofrench(int juliandaycount) Convert a julian day count to a french republic calendar date */ PHP_FUNCTION(jdtofrench) @@ -227,7 +424,6 @@ PHP_FUNCTION(jdtogregorian) } /* }}} */ - /* {{{ proto int frenchtojd(int month, int day, int year) Convert a french republic calendar date to julian day count */ PHP_FUNCTION(frenchtojd) @@ -273,15 +469,13 @@ PHP_FUNCTION(jdtogregorian) daynames = DayNameShort[day]; switch (mymode) { - case 0L: - RETURN_LONG(day); - break; - case 1L: + case CAL_DOW_SHORT: RETURN_STRING(daynamel,1); break; - case 2L: + case CAL_DOW_LONG: RETURN_STRING(daynames,1); break; + case CAL_DOW_DAYNO: default: RETURN_LONG(day); break; @@ -300,39 +494,37 @@ PHP_FUNCTION(jdtogregorian) if (zend_get_parameters_ex(2, &julday, &mode) != SUCCESS) { WRONG_PARAM_COUNT; } - + convert_to_long_ex(julday); convert_to_long_ex(mode); - switch((*mode)->value.lval) { - case 0L: /* gregorian or julian month */ - SdnToGregorian((*julday)->value.lval,&year, &month, &day); - monthname = MonthNameShort[month]; - break; - case 1L: /* gregorian or julian month */ - SdnToGregorian((*julday)->value.lval,&year, &month, &day); - monthname = MonthNameLong[month]; - break; - case 2L: /* gregorian or julian month */ - SdnToJulian((*julday)->value.lval, &year,&month, &day); - monthname = MonthNameShort[month]; - break; - case 3L: /* gregorian or julian month */ - SdnToJulian((*julday)->value.lval, &year,&month, &day); - monthname = MonthNameLong[month]; - break; - case 4L: /* jewish month */ - SdnToJewish((*julday)->value.lval, &year,&month, &day); - monthname = JewishMonthName[month]; - break; - case 5L: /* french month */ - SdnToFrench((*julday)->value.lval, &year,&month, &day); - monthname = FrenchMonthName[month]; - break; - default: /* default gregorian */ - /* FIXME - need to set monthname to something here ?? */ - break; - } + switch((*mode)->value.lval) { + case CAL_MONTH_GREGORIAN_LONG: /* gregorian or julian month */ + SdnToGregorian((*julday)->value.lval,&year, &month, &day); + monthname = MonthNameLong[month]; + break; + case CAL_MONTH_JULIAN_SHORT: /* gregorian or julian month */ + SdnToJulian((*julday)->value.lval, &year,&month, &day); + monthname = MonthNameShort[month]; + break; + case CAL_MONTH_JULIAN_LONG: /* gregorian or julian month */ + SdnToJulian((*julday)->value.lval, &year,&month, &day); + monthname = MonthNameLong[month]; + break; + case CAL_MONTH_JEWISH: /* jewish month */ + SdnToJewish((*julday)->value.lval, &year,&month, &day); + monthname = JewishMonthName[month]; + break; + case CAL_MONTH_FRENCH: /* french month */ + SdnToFrench((*julday)->value.lval, &year,&month, &day); + monthname = FrenchMonthName[month]; + break; + default: /* default gregorian */ + case CAL_MONTH_GREGORIAN_SHORT: /* gregorian or julian month */ + SdnToGregorian((*julday)->value.lval,&year, &month, &day); + monthname = MonthNameShort[month]; + break; + } RETURN_STRING(monthname,1); } diff --git a/ext/calendar/php_calendar.h b/ext/calendar/php_calendar.h index d56d3af19a..73bc96aede 100644 --- a/ext/calendar/php_calendar.h +++ b/ext/calendar/php_calendar.h @@ -25,7 +25,10 @@ PHP_FUNCTION(easter_days); PHP_FUNCTION(easter_date); PHP_FUNCTION(unixtojd); PHP_FUNCTION(jdtounix); - +PHP_FUNCTION(cal_from_jd); +PHP_FUNCTION(cal_to_jd); +PHP_FUNCTION(cal_days_in_month); +PHP_FUNCTION(cal_info); #define phpext_calendar_ptr calendar_module_ptr -- 2.50.1