summaryrefslogtreecommitdiff
path: root/ext/calendar/calendar.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/calendar/calendar.c')
-rw-r--r--ext/calendar/calendar.c755
1 files changed, 755 insertions, 0 deletions
diff --git a/ext/calendar/calendar.c b/ext/calendar/calendar.c
new file mode 100644
index 0000000..010b8d4
--- /dev/null
+++ b/ext/calendar/calendar.c
@@ -0,0 +1,755 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Shane Caraveo <shane@caraveo.com> |
+ | Colin Viebrock <colin@easydns.com> |
+ | Hartmut Holzgraefe <hholzgra@php.net> |
+ | Wez Furlong <wez@thebrainroom.com> |
+ +----------------------------------------------------------------------+
+ */
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef PHP_WIN32
+#define _WINNLS_
+#endif
+
+#include "php.h"
+#include "ext/standard/info.h"
+#include "php_calendar.h"
+#include "sdncal.h"
+
+#include <stdio.h>
+
+/* {{{ arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_unixtojd, 0, 0, 0)
+ ZEND_ARG_INFO(0, timestamp)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_jdtounix, 0)
+ ZEND_ARG_INFO(0, jday)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_cal_info, 0, 0, 0)
+ ZEND_ARG_INFO(0, calendar)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_cal_days_in_month, 0)
+ ZEND_ARG_INFO(0, calendar)
+ ZEND_ARG_INFO(0, month)
+ ZEND_ARG_INFO(0, year)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_cal_to_jd, 0)
+ ZEND_ARG_INFO(0, calendar)
+ ZEND_ARG_INFO(0, month)
+ ZEND_ARG_INFO(0, day)
+ ZEND_ARG_INFO(0, year)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_cal_from_jd, 0)
+ ZEND_ARG_INFO(0, jd)
+ ZEND_ARG_INFO(0, calendar)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_jdtogregorian, 0)
+ ZEND_ARG_INFO(0, juliandaycount)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_gregoriantojd, 0)
+ ZEND_ARG_INFO(0, month)
+ ZEND_ARG_INFO(0, day)
+ ZEND_ARG_INFO(0, year)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_jdtojulian, 0)
+ ZEND_ARG_INFO(0, juliandaycount)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_juliantojd, 0)
+ ZEND_ARG_INFO(0, month)
+ ZEND_ARG_INFO(0, day)
+ ZEND_ARG_INFO(0, year)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_jdtojewish, 0, 0, 1)
+ ZEND_ARG_INFO(0, juliandaycount)
+ ZEND_ARG_INFO(0, hebrew)
+ ZEND_ARG_INFO(0, fl)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_jewishtojd, 0)
+ ZEND_ARG_INFO(0, month)
+ ZEND_ARG_INFO(0, day)
+ ZEND_ARG_INFO(0, year)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_jdtofrench, 0)
+ ZEND_ARG_INFO(0, juliandaycount)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_frenchtojd, 0)
+ ZEND_ARG_INFO(0, month)
+ ZEND_ARG_INFO(0, day)
+ ZEND_ARG_INFO(0, year)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_jddayofweek, 0, 0, 1)
+ ZEND_ARG_INFO(0, juliandaycount)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_jdmonthname, 0)
+ ZEND_ARG_INFO(0, juliandaycount)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_easter_date, 0, 0, 0)
+ ZEND_ARG_INFO(0, year)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_easter_days, 0, 0, 0)
+ ZEND_ARG_INFO(0, year)
+ ZEND_ARG_INFO(0, method)
+ZEND_END_ARG_INFO()
+
+/* }}} */
+
+const zend_function_entry calendar_functions[] = {
+ PHP_FE(jdtogregorian, arginfo_jdtogregorian)
+ PHP_FE(gregoriantojd, arginfo_gregoriantojd)
+ PHP_FE(jdtojulian, arginfo_jdtojulian)
+ PHP_FE(juliantojd, arginfo_juliantojd)
+ PHP_FE(jdtojewish, arginfo_jdtojewish)
+ PHP_FE(jewishtojd, arginfo_jewishtojd)
+ PHP_FE(jdtofrench, arginfo_jdtofrench)
+ PHP_FE(frenchtojd, arginfo_frenchtojd)
+ PHP_FE(jddayofweek, arginfo_jddayofweek)
+ PHP_FE(jdmonthname, arginfo_jdmonthname)
+ PHP_FE(easter_date, arginfo_easter_date)
+ PHP_FE(easter_days, arginfo_easter_days)
+ PHP_FE(unixtojd, arginfo_unixtojd)
+ PHP_FE(jdtounix, arginfo_jdtounix)
+ PHP_FE(cal_to_jd, arginfo_cal_to_jd)
+ PHP_FE(cal_from_jd, arginfo_cal_from_jd)
+ PHP_FE(cal_days_in_month, arginfo_cal_days_in_month)
+ PHP_FE(cal_info, arginfo_cal_info)
+ PHP_FE_END
+};
+
+
+zend_module_entry calendar_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "calendar",
+ calendar_functions,
+ PHP_MINIT(calendar),
+ NULL,
+ NULL,
+ NULL,
+ PHP_MINFO(calendar),
+ NO_VERSION_YET,
+ STANDARD_MODULE_PROPERTIES,
+};
+
+#ifdef COMPILE_DL_CALENDAR
+ZEND_GET_MODULE(calendar)
+#endif
+
+/* this order must match the conversion table below */
+enum cal_name_type_t {
+ 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
+};
+
+/* for heb_number_to_chars */
+static char alef_bet[25] = "0אבגדהוזחטיכלמנסעפצקרשת";
+
+#define CAL_JEWISH_ADD_ALAFIM_GERESH 0x2
+#define CAL_JEWISH_ADD_ALAFIM 0x4
+#define CAL_JEWISH_ADD_GERESHAYIM 0x8
+
+PHP_MINIT_FUNCTION(calendar)
+{
+ 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);
+/* constants for easter calculation */
+ REGISTER_LONG_CONSTANT("CAL_EASTER_DEFAULT", CAL_EASTER_DEFAULT, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("CAL_EASTER_ROMAN", CAL_EASTER_ROMAN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("CAL_EASTER_ALWAYS_GREGORIAN", CAL_EASTER_ALWAYS_GREGORIAN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("CAL_EASTER_ALWAYS_JULIAN", CAL_EASTER_ALWAYS_JULIAN, CONST_CS | CONST_PERSISTENT);
+/* constants for Jewish date formatting */
+ REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_ALAFIM_GERESH", CAL_JEWISH_ADD_ALAFIM_GERESH, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_ALAFIM", CAL_JEWISH_ADD_ALAFIM, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("CAL_JEWISH_ADD_GERESHAYIM", CAL_JEWISH_ADD_GERESHAYIM, CONST_CS | CONST_PERSISTENT);
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(calendar)
+{
+ php_info_print_table_start();
+ php_info_print_table_row(2, "Calendar support", "enabled");
+ php_info_print_table_end();
+}
+
+static void _php_cal_info(int cal, zval **ret)
+{
+ zval *months, *smonths;
+ int i;
+ struct cal_entry_t *calendar;
+
+ calendar = &cal_conversion_table[cal];
+ array_init(*ret);
+
+ 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(*ret, "months", months);
+ add_assoc_zval(*ret, "abbrevmonths", smonths);
+ add_assoc_long(*ret, "maxdaysinmonth", calendar->max_days_in_month);
+ add_assoc_string(*ret, "calname", calendar->name, 1);
+ add_assoc_string(*ret, "calsymbol", calendar->symbol, 1);
+
+}
+
+/* {{{ proto array cal_info([int calendar])
+ Returns information about a particular calendar */
+PHP_FUNCTION(cal_info)
+{
+ long cal = -1;
+
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &cal) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (cal == -1) {
+ int i;
+ zval *val;
+
+ array_init(return_value);
+
+ for (i = 0; i < CAL_NUM_CALS; i++) {
+ MAKE_STD_ZVAL(val);
+ _php_cal_info(i, &val);
+ add_index_zval(return_value, i, val);
+ }
+ return;
+ }
+
+
+ if (cal != -1 && (cal < 0 || cal >= CAL_NUM_CALS)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
+ RETURN_FALSE;
+ }
+
+ _php_cal_info(cal, &return_value);
+
+}
+/* }}} */
+
+/* {{{ 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)
+{
+ long cal, month, year;
+ struct cal_entry_t *calendar;
+ long sdn_start, sdn_next;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &cal, &month, &year) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (cal < 0 || cal >= CAL_NUM_CALS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
+ RETURN_FALSE;
+ }
+
+ calendar = &cal_conversion_table[cal];
+
+ sdn_start = calendar->to_jd(year, month, 1);
+
+ if (sdn_start == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid date.");
+ RETURN_FALSE;
+ }
+
+ sdn_next = calendar->to_jd(year, 1 + month, 1);
+
+ if (sdn_next == 0) {
+ /* If the next month is invalid, then we need to try the first month of
+ * the next year, bearing in mind that the next year after 1 BCE is
+ * actually 1 AD and not 0. */
+ if (year == -1) {
+ sdn_next = calendar->to_jd(1, 1, 1);
+ }
+ else {
+ sdn_next = calendar->to_jd(year + 1, 1, 1);
+ }
+ }
+
+ RETURN_LONG(sdn_next - sdn_start);
+}
+/* }}} */
+
+/* {{{ proto int cal_to_jd(int calendar, int month, int day, int year)
+ Converts from a supported calendar to Julian Day Count */
+PHP_FUNCTION(cal_to_jd)
+{
+ long cal, month, day, year;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &cal, &month, &day, &year) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (cal < 0 || cal >= CAL_NUM_CALS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld.", cal);
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(cal_conversion_table[cal].to_jd(year, month, day));
+}
+/* }}} */
+
+/* {{{ proto array cal_from_jd(int jd, int calendar)
+ Converts from Julian Day Count to a supported calendar and return extended information */
+PHP_FUNCTION(cal_from_jd)
+{
+ long jd, cal;
+ int month, day, year, dow;
+ char date[16];
+ struct cal_entry_t *calendar;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "ll", &jd, &cal) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (cal < 0 || cal >= CAL_NUM_CALS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid calendar ID %ld", cal);
+ RETURN_FALSE;
+ }
+ calendar = &cal_conversion_table[cal];
+
+ array_init(return_value);
+
+ calendar->from_jd(jd, &year, &month, &day);
+
+ snprintf(date, sizeof(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(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)
+ Converts a julian day count to a gregorian calendar date */
+PHP_FUNCTION(jdtogregorian)
+{
+ long julday;
+ int year, month, day;
+ char date[16];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ SdnToGregorian(julday, &year, &month, &day);
+ snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
+
+ RETURN_STRING(date, 1);
+}
+/* }}} */
+
+/* {{{ proto int gregoriantojd(int month, int day, int year)
+ Converts a gregorian calendar date to julian day count */
+PHP_FUNCTION(gregoriantojd)
+{
+ long year, month, day;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(GregorianToSdn(year, month, day));
+}
+/* }}} */
+
+/* {{{ proto string jdtojulian(int juliandaycount)
+ Convert a julian day count to a julian calendar date */
+PHP_FUNCTION(jdtojulian)
+{
+ long julday;
+ int year, month, day;
+ char date[16];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ SdnToJulian(julday, &year, &month, &day);
+ snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
+
+ RETURN_STRING(date, 1);
+}
+/* }}} */
+
+/* {{{ proto int juliantojd(int month, int day, int year)
+ Converts a julian calendar date to julian day count */
+PHP_FUNCTION(juliantojd)
+{
+ long year, month, day;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(JulianToSdn(year, month, day));
+}
+/* }}} */
+
+/* {{{ heb_number_to_chars*/
+/*
+caution: the Hebrew format produces non unique result.
+for example both: year '5' and year '5000' produce 'ה'.
+use the numeric one for calculations.
+ */
+static char *heb_number_to_chars(int n, int fl, char **ret)
+{
+ char *p, old[18], *endofalafim;
+
+ p = endofalafim = old;
+/*
+ prevents the option breaking the jewish beliefs, and some other
+ critical resources ;)
+ */
+ if (n > 9999 || n < 1) {
+ *ret = NULL;
+ return NULL;
+ }
+
+/* alafim (thousands) case */
+ if (n / 1000) {
+ *p = alef_bet[n / 1000];
+ p++;
+
+ if (CAL_JEWISH_ADD_ALAFIM_GERESH & fl) {
+ *p = '\'';
+ p++;
+ }
+ if (CAL_JEWISH_ADD_ALAFIM & fl) {
+ strcpy(p, " אלפים ");
+ p += 7;
+ }
+
+ endofalafim = p;
+ n = n % 1000;
+ }
+
+/* tav-tav (tav=400) case */
+ while (n >= 400) {
+ *p = alef_bet[22];
+ p++;
+ n -= 400;
+ }
+
+/* meot (hundreads) case */
+ if (n >= 100) {
+ *p = alef_bet[18 + n / 100];
+ p++;
+ n = n % 100;
+ }
+
+/* tet-vav & tet-zain case (special case for 15 and 16) */
+ if (n == 15 || n == 16) {
+ *p = alef_bet[9];
+ p++;
+ *p = alef_bet[n - 9];
+ p++;
+ } else {
+/* asarot (tens) case */
+ if (n >= 10) {
+ *p = alef_bet[9 + n / 10];
+ p++;
+ n = n % 10;
+ }
+
+/* yehidot (ones) case */
+ if (n > 0) {
+ *p = alef_bet[n];
+ p++;
+ }
+ }
+
+ if (CAL_JEWISH_ADD_GERESHAYIM & fl) {
+ switch (p - endofalafim) {
+ case 0:
+ break;
+ case 1:
+ *p = '\'';
+ p++;
+ break;
+ default:
+ *(p) = *(p - 1);
+ *(p - 1) = '"';
+ p++;
+ }
+ }
+
+ *p = '\0';
+ *ret = estrndup(old, (p - old) + 1);
+ p = *ret;
+ return p;
+}
+/* }}} */
+
+/* {{{ proto string jdtojewish(int juliandaycount [, bool hebrew [, int fl]])
+ Converts a julian day count to a jewish calendar date */
+PHP_FUNCTION(jdtojewish)
+{
+ long julday, fl = 0;
+ zend_bool heb = 0;
+ int year, month, day;
+ char date[16], hebdate[32];
+ char *dayp, *yearp;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|bl", &julday, &heb, &fl) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ SdnToJewish(julday, &year, &month, &day);
+ if (!heb) {
+ snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
+ RETURN_STRING(date, 1);
+ } else {
+ if (year <= 0 || year > 9999) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Year out of range (0-9999).");
+ RETURN_FALSE;
+ }
+
+ snprintf(hebdate, sizeof(hebdate), "%s %s %s", heb_number_to_chars(day, fl, &dayp), JewishMonthHebName[month], heb_number_to_chars(year, fl, &yearp));
+
+ if (dayp) {
+ efree(dayp);
+ }
+ if (yearp) {
+ efree(yearp);
+ }
+
+ RETURN_STRING(hebdate, 1);
+
+ }
+}
+/* }}} */
+
+/* {{{ proto int jewishtojd(int month, int day, int year)
+ Converts a jewish calendar date to a julian day count */
+PHP_FUNCTION(jewishtojd)
+{
+ long year, month, day;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(JewishToSdn(year, month, day));
+}
+/* }}} */
+
+/* {{{ proto string jdtofrench(int juliandaycount)
+ Converts a julian day count to a french republic calendar date */
+PHP_FUNCTION(jdtofrench)
+{
+ long julday;
+ int year, month, day;
+ char date[16];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &julday) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ SdnToFrench(julday, &year, &month, &day);
+ snprintf(date, sizeof(date), "%i/%i/%i", month, day, year);
+
+ RETURN_STRING(date, 1);
+}
+/* }}} */
+
+/* {{{ proto int frenchtojd(int month, int day, int year)
+ Converts a french republic calendar date to julian day count */
+PHP_FUNCTION(frenchtojd)
+{
+ long year, month, day;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &month, &day, &year) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ RETURN_LONG(FrenchToSdn(year, month, day));
+}
+/* }}} */
+
+/* {{{ proto mixed jddayofweek(int juliandaycount [, int mode])
+ Returns name or number of day of week from julian day count */
+PHP_FUNCTION(jddayofweek)
+{
+ long julday, mode = CAL_DOW_DAYNO;
+ int day;
+ char *daynamel, *daynames;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &julday, &mode) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ day = DayOfWeek(julday);
+ daynamel = DayNameLong[day];
+ daynames = DayNameShort[day];
+
+ switch (mode) {
+ case CAL_DOW_SHORT:
+ RETURN_STRING(daynamel, 1);
+ break;
+ case CAL_DOW_LONG:
+ RETURN_STRING(daynames, 1);
+ break;
+ case CAL_DOW_DAYNO:
+ default:
+ RETURN_LONG(day);
+ break;
+ }
+}
+/* }}} */
+
+/* {{{ proto string jdmonthname(int juliandaycount, int mode)
+ Returns name of month for julian day count */
+PHP_FUNCTION(jdmonthname)
+{
+ long julday, mode;
+ char *monthname = NULL;
+ int month, day, year;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &julday, &mode) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ switch (mode) {
+ case CAL_MONTH_GREGORIAN_LONG: /* gregorian or julian month */
+ SdnToGregorian(julday, &year, &month, &day);
+ monthname = MonthNameLong[month];
+ break;
+ case CAL_MONTH_JULIAN_SHORT: /* gregorian or julian month */
+ SdnToJulian(julday, &year, &month, &day);
+ monthname = MonthNameShort[month];
+ break;
+ case CAL_MONTH_JULIAN_LONG: /* gregorian or julian month */
+ SdnToJulian(julday, &year, &month, &day);
+ monthname = MonthNameLong[month];
+ break;
+ case CAL_MONTH_JEWISH: /* jewish month */
+ SdnToJewish(julday, &year, &month, &day);
+ monthname = JewishMonthName[month];
+ break;
+ case CAL_MONTH_FRENCH: /* french month */
+ SdnToFrench(julday, &year, &month, &day);
+ monthname = FrenchMonthName[month];
+ break;
+ default: /* default gregorian */
+ case CAL_MONTH_GREGORIAN_SHORT: /* gregorian or julian month */
+ SdnToGregorian(julday, &year, &month, &day);
+ monthname = MonthNameShort[month];
+ break;
+ }
+
+ RETURN_STRING(monthname, 1);
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */