Edit report at http://bugs.php.net/bug.php?id=52744&edit=1

 ID:                 52744
 Updated by:         ahar...@php.net
 Reported by:        gpap at internet dot gr
 Summary:            cal_days_in_month
-Status:             Open
+Status:             Assigned
 Type:               Bug
 Package:            Calendar related
 Operating System:   all
 PHP Version:        5.3SVN-2010-08-30 (snap)
-Assigned To:        
+Assigned To:        aharvey
 Block user comment: N



Previous Comments:
------------------------------------------------------------------------
[2010-08-30 18:16:53] gpap at internet dot gr

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 this bug report at http://bugs.php.net/bug.php?id=52744&edit=1

Reply via email to