Re: Date_Calc::weekOfYear() bug?
| From: | Jesus M. Castagnetto | 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