Re: Date_Calc::weekOfYear() bug?

From: Date: Tue, 26 Nov 2002 19:25:21 +0000
Subject: Re: Date_Calc::weekOfYear() bug?
References: 1  Groups: php.pear.general 
Request: Send a blank email to pear-general+get-2851@lists.php.net to get a copy of this message
Here is a patch that implements a gregorian to ISO conversion. Got the algorithm from http://personal.ecu.edu/mccartyr/ISOwdALG.txt, although it seems to me that the last part of that algorithm is missing a +1 when the ISO week number is calculated (labelled as "kludge" in the patch). This can be used for the other methods. I testes if w/ the dates from the bug report and from the email sent to this list: <?php require './Calc.php'; echo Date_Calc::gregorianToISO(1998,1,5) . ", "; echo Date_Calc::gregorianToISO(1998,1,6)."\n"; echo Date_Calc::gregorianToISO(2004,1,5) . ", "; echo Date_Calc::gregorianToISO(2004,1,6)."\n"; for ($i = 17; $i < 21; $i++) { echo ">> ".Date_Calc::gregorianToISO(2002,11,$i)."\n"; } ?> Pierre-Alain: if you want I can commit this to CVS directly, in case your connection is not too good today. ==== PATCH BELOW ==== --- Calc.php_orig Tue Nov 26 10:23:47 2002 +++ Calc.php Tue Nov 26 11:13:47 2002 @@ -1624,6 +1624,65 @@ return($weekdays); } // end func getWeekDays -} // end class Date_calendar + /** + * Converts from Gregorian Year-Month-Day to ISO YearNumber-WeekNumber-WeekDay + * + * Uses ISO 8601 definitions. + * Algorithm from Rick McCarty, 1999 at http://personal.ecu.edu/mccartyr/ISOwdALG.txt + */ + function gregorianToISO($year, $month, $day) { + $mnth = array (0,31,59,90,120,151,181,212,243,273,304,334); + $y_isleap = Date_Calc::isLeapYear($year); + $y_1_isleap = Date_Calc::isLeapYear($year - 1); + $day_of_year_number = $day + $mnth[$month - 1]; + if ($y_isleap && $month > 2) { + $day_of_year_number++; + } + // find Jan 1 weekday (monday = 1, sunday = 7) + $yy = ($year - 1) % 100; + $c = ($year - 1) - $yy; + $g = $yy + intval($yy/4); + $jan1_weekday = 1 + intval((((($c / 100) % 4) * 5) + $g) % 7); + // weekday for year-month-day + $h = $day_of_year_number + ($jan1_weekday - 1); + $weekday = 1 + intval(($h - 1) % 7); + // find if Y M D falls in YearNumber Y-1, WeekNumber 52 or + if ($day_of_year_number <= (8 - $jan1_weekday) && $jan1_weekday > 4){ + $yearnumber = $year - 1; + if ($jan1_weekday == 5 || ($jan1_weekday == 6 && $y_1_isleap)) { + $weeknumber = 53; + } else { + $weeknumber = 52; + } + } else { + $yearnumber = $year; + } + // find if Y M D falls in YearNumber Y+1, WeekNumber 1 + if ($yearnumber == $year) { + if ($y_isleap) { + $i = 366; + } else { + $i = 365; + } + if (($i - $day_of_year_number) < (4 - $weekday)) { + $yearnumber++; + $weeknumber = 1; + } + } + // find if Y M D falls in YearNumber Y, WeekNumber 1 through 53 + if ($yearnumber == $year) { + $j = $day_of_year_number + (7 - $weekday) + ($jan1weekday - 1); + $weeknumber = intval($j / 7) + 1; // kludge!!! - JMC + if ($jan1_weekday > 4) { + $weeknumber--; + } + } + // put it all together + if ($weeknumber < 10) + $weeknumber = '0'.$weeknumber; + return "{$yearnumber}-{$weeknumber}-{$weekday}"; + } + +} // end class Date_Calc ?> ===== --- Jesus M. Castagnetto (jcastagnetto@yahoo.com) Research: http://metallo.scripps.edu/ Personal: http://www.castagnetto.org/ __________________________________________________ Do you Yahoo!? Yahoo! Mail Plus - Powerful. Affordable. Sign up now. http://mailplus.yahoo.com

« previous php.pear.general (#2851) next »