aesthetics1 Posted April 18, 2013 Share Posted April 18, 2013 Hi there. I'm having trouble with a holiday calculation script. I picked it up online and have simply added/removed a few holidays to fit my needs. It seems to calculate everything properly, except for Cesar Chavez day (March 31st). The script basically looks for the holiday, and then determines what day of the week it falls on. If it's a weekday, great. If it's on a Saturday, then Friday is the observed day, so it should return Friday. If it's Sunday, it should return Monday. As I said above, it works for the most part, but Cesar Chavez day won't compute (returns Jan 1 1970 date) in 2013, 2019, etc. Looking at my code, can anyone determine what's going on? Thanks in advance. <?php /* US Holiday Calculations in PHP * Version 1.02 * by Dan Kaplan <design@abledesign.com> * Last Modified: April 15, 2001 * ------------------------------------------------------------------------ * The holiday calculations on this page were assembled for * use in MyCalendar: http://abledesign.com/programs/MyCalendar/ * * USE THIS LIBRARY AT YOUR OWN RISK; no warranties are expressed or * implied. You may modify the file however you see fit, so long as * you retain this header information and any credits to other sources * throughout the file. If you make any modifications or improvements, * please send them via email to Dan Kaplan <design@abledesign.com>. * ------------------------------------------------------------------------ */ if(isset($_POST['year'])) { $current_year = $_POST['year']; } else { $current_year = date('Y'); } // Gregorian Calendar = 1583 or later if (!$current_year || ($current_year < 1583) || ($current_year > 4099)) { $current_year = date("Y",time()); // use the current year if nothing is specified } function format_date($year, $month, $day) { // pad single digit months/days with a leading zero for consistency (aesthetics) // and format the date as desired: YYYY-MM-DD by default if (strlen($month) == 1) { $month = "0". $month; } if (strlen($day) == 1) { $day = "0". $day; } $date = $year ."-". $month ."-". $day; return $date; } // the following function get_holiday() is based on the work done by // Marcos J. Montes: http://www.smart.net/~mmontes/ushols.html // // if $week is not passed in, then we are checking for the last week of the month function get_holiday($year, $month, $day_of_week, $week="") { if ( (($week != "") && (($week > 5) || ($week < 1))) || ($day_of_week > 6) || ($day_of_week < 0) ) { // $day_of_week must be between 0 and 6 (Sun=0, ... Sat=6); $week must be between 1 and 5 return FALSE; } else { if (!$week || ($week == "")) { $lastday = date("t", mktime(0,0,0,$month,1,$year)); $temp = (date("w",mktime(0,0,0,$month,$lastday,$year)) - $day_of_week) % 7; } else { $temp = ($day_of_week - date("w",mktime(0,0,0,$month,1,$year))) % 7; } if ($temp < 0) { $temp += 7; } if (!$week || ($week == "")) { $day = $lastday - $temp; } else { $day = (7 * $week) - 6 + $temp; } return format_date($year, $month, $day); } } function observed_day($year, $month, $day) { // sat -> fri & sun -> mon, any exceptions? // // should check $lastday for bumping forward and $firstday for bumping back, // although New Year's & Easter look to be the only holidays that potentially // move to a different month, and both are accounted for. $dow = date("w", mktime(0, 0, 0, $month, $day, $year)); if ($dow == 0) { $dow = $day + 1; } elseif ($dow == 6) { if (($month == 1) && ($day == 1)) { // New Year's on a Saturday $year--; $month = 12; $dow = 31; } else { $dow = $day - 1; } } else { $dow = $day; } return format_date($year, $month, $dow); } function calculate_easter($y) { // In the text below, 'intval($var1/$var2)' represents an integer division neglecting // the remainder, while % is division keeping only the remainder. So 30/7=4, and 30%7=2 // // This algorithm is from Practical Astronomy With Your Calculator, 2nd Edition by Peter // Duffett-Smith. It was originally from Butcher's Ecclesiastical Calendar, published in // 1876. This algorithm has also been published in the 1922 book General Astronomy by // Spencer Jones; in The Journal of the British Astronomical Association (Vol.88, page // 91, December 1977); and in Astronomical Algorithms (1991) by Jean Meeus. $a = $y%19; $b = intval($y/100); $c = $y%100; $d = intval($b/4); $e = $b%4; $f = intval(($b+8)/25); $g = intval(($b-$f+1)/3); $h = (19*$a+$b-$d-$g+15)%30; $i = intval($c/4); $k = $c%4; $l = (32+2*$e+2*$i-$h-$k)%7; $m = intval(($a+11*$h+22*$l)/451); $p = ($h+$l-7*$m+114)%31; $EasterMonth = intval(($h+$l-7*$m+114)/31); // [3 = March, 4 = April] $EasterDay = $p+1; // (day in Easter Month) return format_date($y, $EasterMonth, $EasterDay); } ///////////////////////////////////////////////////////////////////////////// // end of calculation functions; place the dates you wish to calculate below ///////////////////////////////////////////////////////////////////////////// ?> <?php // format to use: // // get_holiday("year", "month", "day_of_week", "week_of_month"); // get_holiday("year", "month", "day_of_week); // no 4th field indicates last week of month check // format_date("year", "month", "day"); ?> <div class="clearfix"> <form action="index.php?section=holidays" method="post"> <p><b>Enter a Year:</b></p> <p class="float-left"><input type="text" name="year" value="<?php echo $current_year; ?>" size="4" maxlength="4"></p> <p class="float-left"><input class="button grey small" type="submit" value="Go"></p> </form> </div> <?php echo "<p><b>".$current_year." Holidays</b></p>"; echo '<ul class="bullets">'; echo "<li>New Year's Day ". date("F d, Y", strtotime(observed_day($current_year, 1, 1))); echo "<li>Lincoln Day ". date("F d, Y", strtotime(format_date($current_year, 2, 12))); echo "<li>Martin Luther King Day Observed (Third Monday in January) = ". date("F d, Y", strtotime(get_holiday($current_year, 1, 1, 3))); echo "<li>President's Day Observed (Third Monday in February) = ". date("F d, Y", strtotime(get_holiday($current_year, 2, 1, 3))); echo "<li>Cesar Chavez Day = ". date("F d, Y", strtotime(observed_day($current_year, 3, 31))); echo "<li>Memorial Day Observed (Last Monday in May) = ". date("F d, Y", strtotime(get_holiday($current_year, 5, 1))); echo "<li>Independence Day Observed = ". date("F d, Y", strtotime(observed_day($current_year, 7, 4))); echo "<li>Labor Day Observed (First Monday in September) = ". date("F d, Y", strtotime(get_holiday($current_year, 9, 1, 1))); echo "<li>Columbus Day Observed (Second Monday in October) = ". date("F d, Y", strtotime(get_holiday($current_year, 10, 1, 2))); // Veteran's Day Observed - November 11th ? echo "<li>Thanksgiving (Fourth Thursday in November) = ". date("F d, Y", strtotime(get_holiday($current_year, 11, 4, 4))); echo "<li>Day After Thanksgiving (Friday after Thanksgiving) = ". date("F d, Y", strtotime("+1 day", strtotime(get_holiday($current_year, 11, 4, 4)))); echo "<li>Christmas Day = ". date("F d, Y", strtotime(observed_day($current_year, 12, 25))); echo "</ul>"; ?> Quote Link to comment Share on other sites More sharing options...
requinix Posted April 18, 2013 Share Posted April 18, 2013 if ($dow == 0) { $dow = $day + 1;You don't have anything that wraps the last day of the month on Sunday to be the Monday in the next month. Same way you don't have anything that wraps the first day of the month on Saturday to be the Friday of the previous month. Quote Link to comment Share on other sites More sharing options...
lemmin Posted April 18, 2013 Share Posted April 18, 2013 It looks to be a glitch in the observed_day() function. The 31st of March 2013 is on a Sunday, so it adds a day and makes it the 32nd of March, which strtotime() can't parse, so it returns a null timestamp. Quote Link to comment Share on other sites More sharing options...
Solution lemmin Posted April 18, 2013 Solution Share Posted April 18, 2013 It even references it in the comments hehe: // although New Year's & Easter look to be the only holidays that potentially // move to a different month, and both are accounted for. Try changing that function to this: function observed_day($year, $month, $day) { // sat -> fri & sun -> mon, any exceptions? $dow = date("w", mktime(0, 0, 0, $month, $day, $year)); $daystring = $year . '-' . $month . '-' . $day; if ($dow == 0) return $daystring . ' +1 day'; elseif ($dow == 6) return $daystring . ' -1 day'; return $daystring; } Quote Link to comment Share on other sites More sharing options...
aesthetics1 Posted April 18, 2013 Author Share Posted April 18, 2013 Thank you very much requinix/lemmin. The updated function fixed the problem as far as I can tell. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.