From: Operating system: all PHP version: 5.3SVN-2010-08-30 (snap) Package: Calendar related Bug Type: Bug Bug description:cal_days_in_month
Description: ------------ Function cal_days_in_month returns wrong result for December 1 BCE: echo cal_days_in_month(CAL_GREGORIAN, 12, -1) returns -1721395 echo cal_days_in_month(CAL_JULIAN, 12, -1) returns -1721393 The function uses julian day count internally to calculate the day count difference between the 1st day of the supplied month and the 1st day of the next month. The next month of December 1 BCE (year -1) is January 1 CE (year 1, there is no year zero). But when cal_days_in_month calculates the next year as year+1, it does not check for year zero, so it tries to calculate the julian day for 1st January 0, which returns 0 and consequently the wrong result of days in December 1 BCE is returned. actual function code taken from latest svn snapshot php5.3-201008301230 (/ext/calendar.c): ----------------------- 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 invalid, try first month of the next year... */ sdn_next = calendar->to_jd(year + 1, 1, 1); } RETURN_LONG(sdn_next - sdn_start); } ----------------------- The following correction is proposed: ----------------------- if (sdn_next == 0) { /* if invalid, try first month of the next year... */ - sdn_next = calendar->to_jd(year + 1, 1, 1); + if (year == -1) { + sdn_next = calendar->to_jd(1, 1, 1); + } else { + sdn_next = calendar->to_jd(year + 1, 1, 1); + } } ----------------------- Test script: --------------- <?php // returns -1721395 instead of 31 echo cal_days_in_month(CAL_GREGORIAN, 12, -1); // returns -1721393 instead of 31 echo cal_days_in_month(CAL_JULIAN, 12, -1); ?> Expected result: ---------------- 31 31 Actual result: -------------- -1721395 -1721393 -- Edit bug report at http://bugs.php.net/bug.php?id=52744&edit=1 -- Try a snapshot (PHP 5.2): http://bugs.php.net/fix.php?id=52744&r=trysnapshot52 Try a snapshot (PHP 5.3): http://bugs.php.net/fix.php?id=52744&r=trysnapshot53 Try a snapshot (trunk): http://bugs.php.net/fix.php?id=52744&r=trysnapshottrunk Fixed in SVN: http://bugs.php.net/fix.php?id=52744&r=fixed Fixed in SVN and need be documented: http://bugs.php.net/fix.php?id=52744&r=needdocs Fixed in release: http://bugs.php.net/fix.php?id=52744&r=alreadyfixed Need backtrace: http://bugs.php.net/fix.php?id=52744&r=needtrace Need Reproduce Script: http://bugs.php.net/fix.php?id=52744&r=needscript Try newer version: http://bugs.php.net/fix.php?id=52744&r=oldversion Not developer issue: http://bugs.php.net/fix.php?id=52744&r=support Expected behavior: http://bugs.php.net/fix.php?id=52744&r=notwrong Not enough info: http://bugs.php.net/fix.php?id=52744&r=notenoughinfo Submitted twice: http://bugs.php.net/fix.php?id=52744&r=submittedtwice register_globals: http://bugs.php.net/fix.php?id=52744&r=globals PHP 4 support discontinued: http://bugs.php.net/fix.php?id=52744&r=php4 Daylight Savings: http://bugs.php.net/fix.php?id=52744&r=dst IIS Stability: http://bugs.php.net/fix.php?id=52744&r=isapi Install GNU Sed: http://bugs.php.net/fix.php?id=52744&r=gnused Floating point limitations: http://bugs.php.net/fix.php?id=52744&r=float No Zend Extensions: http://bugs.php.net/fix.php?id=52744&r=nozend MySQL Configuration Error: http://bugs.php.net/fix.php?id=52744&r=mysqlcfg