Skip to content

Instantly share code, notes, and snippets.

@gavinblair
Created August 15, 2010 17:57
Show Gist options
  • Save gavinblair/525746 to your computer and use it in GitHub Desktop.
Save gavinblair/525746 to your computer and use it in GitHub Desktop.
<?php
//ini_set("display_errors","on");
//***************
//
//Author: Andrew McClenaghan / Echidna Solutions Corp.
//Date: August 3, 2010
//
//***************
define('HOLIDAYS','2009-10-12|2009-12-25|2009-12-26|2010-01-01|2010-02-15|2010-04-02|2010-04-05|2010-05-24|2010-07-01|2010-08-02|2010-09-06');//the set of all stat holidays for the year
define('PICKUP_INTERVAL_IN_DAYS',8);//number of days in the pickup schedule
define('PICKUP_OUTPUTS',52);//number of pickup dates to output
define('INITIAL_PICKUP_DATE',"2009-10-05");//set to a valid garbage day for a zone, in this example zone c
//set initial date
$pickup_date = INITIAL_PICKUP_DATE;
for ($i=0;$i<PICKUP_OUTPUTS;$i++) //output a set number of pickup dates
{
//save current pickup_date
$previous_pickup_date = $pickup_date;
//advance to next pickup date
$date_array = explode("-",$pickup_date);
$pickup_date=date("Y-m-d",mktime(0,0,0,$date_array[1],$date_array[2]+PICKUP_INTERVAL_IN_DAYS,$date_array[0]));
//loop and increment one day a time until a valid pickup_date is found
//a valid pickup day is one that is a weekday and not a holiday
while (!is_valid_pickup_date($pickup_date))
{
//advance one day
$pickup_date = increment_date($pickup_date);
}
//check to see if the past interval had a holiday // and if so advance an extra day for each holiday
$pickup_date = increment_date($pickup_date,number_of_holidays_in_previous_interval($pickup_date,$previous_pickup_date));
//ensure once again that the adjusted pickup date is still valid
while (!is_valid_pickup_date($pickup_date))
{
//advance one day
$pickup_date = increment_date($pickup_date);
}
echo "<li>".date("l, M. d, Y",strtotime($pickup_date))."</li>";
}
function number_of_holidays_in_previous_interval($pickup_date,$previous_pickup_date)
{//calculate the number of holidays that existed in a date interval and return the integer
$holiday_array = explode("|",HOLIDAYS);
$date_array = explode("-",$pickup_date);
$num_holidays = 0;
for($days=datediff("d",$previous_pickup_date,$pickup_date);$days>=0;$days--)
{
$tempDate = date("Y-m-d",mktime(0,0,0,$date_array[1],$date_array[2]-$days,$date_array[0]));
if (in_array($tempDate,$holiday_array))
$num_holidays++;
}
return $num_holidays;
}
function increment_date($pickup_date,$inc=1)
{//increment and return the date by $inc number of days
$date_array = explode("-",$pickup_date);
return date("Y-m-d",mktime(0,0,0,$date_array[1],$date_array[2]+$inc,$date_array[0]));
}
function is_holiday($pickup_date)
{//check to see if the date passed is a holiday
$holiday_array = explode("|",HOLIDAYS);
return in_array($pickup_date,$holiday_array);
}
function is_weekday($pickup_date)
{//check to see if the date passed is a weekday
$weekday_array = array(1,2,3,4,5);
return in_array(date("N",strtotime($pickup_date)),$weekday_array);
}
function is_valid_pickup_date($pickup_date)
{//is not a holiday? and is a weekday?
return (!is_holiday($pickup_date) && is_weekday($pickup_date));
}
function datediff($interval, $datefrom, $dateto, $using_timestamps = false) {
// borrowed from somewhere.... need a reference
// $interval can be:
// yyyy - Number of full years
// q - Number of full quarters
// m - Number of full months
// y - Difference between day numbers
// (eg 1st Jan 2004 is "1", the first day. 2nd Feb 2003 is "33". The datediff is "-32".)
// d - Number of full days
// w - Number of full weekdays
// ww - Number of full weeks
// h - Number of full hours
// n - Number of full minutes
// s - Number of full seconds (default)
//
if (!$using_timestamps) {
$datefrom = strtotime($datefrom, 0);
$dateto = strtotime($dateto, 0);
}
$difference = $dateto - $datefrom; // Difference in seconds
switch($interval) {
case 'yyyy': // Number of full years
$years_difference = floor($difference / 31536000);
if (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom), date("j", $datefrom), date("Y", $datefrom)+$years_difference) > $dateto) {
$years_difference--;
}
if (mktime(date("H", $dateto), date("i", $dateto), date("s", $dateto), date("n", $dateto), date("j", $dateto), date("Y", $dateto)-($years_difference+1)) > $datefrom) {
$years_difference++;
}
$datediff = $years_difference;
break;
case "q": // Number of full quarters
$quarters_difference = floor($difference / 8035200);
while (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom)+($quarters_difference*3), date("j", $dateto), date("Y", $datefrom)) < $dateto) {
$months_difference++;
}
$quarters_difference--;
$datediff = $quarters_difference;
break;
case "m": // Number of full months
$months_difference = floor($difference / 2678400);
while (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom)+($months_difference), date("j", $dateto), date("Y", $datefrom)) < $dateto) {
$months_difference++;
}
$months_difference--;
$datediff = $months_difference;
break;
case 'y': // Difference between day numbers
$datediff = date("z", $dateto) - date("z", $datefrom);
break;
case "d": // Number of full days
$datediff = floor($difference / 86400);
break;
case "w": // Number of full weekdays
$days_difference = floor($difference / 86400);
$weeks_difference = floor($days_difference / 7); // Complete weeks
$first_day = date("w", $datefrom);
$days_remainder = floor($days_difference % 7);
$odd_days = $first_day + $days_remainder; // Do we have a Saturday or Sunday in the remainder?
if ($odd_days > 7) { // Sunday
$days_remainder--;
}
if ($odd_days > 6) { // Saturday
$days_remainder--;
}
$datediff = ($weeks_difference * 5) + $days_remainder;
break;
case "ww": // Number of full weeks
$datediff = floor($difference / 604800);
break;
case "h": // Number of full hours
$datediff = floor($difference / 3600);
break;
case "n": // Number of full minutes
$datediff = floor($difference / 60);
break;
default: // Number of full seconds (default)
$datediff = $difference;
break;
}
return $datediff;
}
@SeanJA
Copy link

SeanJA commented Aug 15, 2010

What's this then?

@SeanJA
Copy link

SeanJA commented Aug 15, 2010

datediff('yyyy', 'today', 'tomorrow', false); => NAN... I would have expected 0

@gavinblair
Copy link
Author

From http://londontrash.pbworks.com/Pickup-Date-Generator-Algorithm

An algorithm to determine if it is garbage day. In London garbage is picked up on an 8 day cycle, pausing for holidays. FYI, putting your garbage out on the wrong day results in a $500 fine!

@SeanJA
Copy link

SeanJA commented Aug 15, 2010

The datediff function resembles this one: http://www.addedbytes.com/code/php-datediff-function/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment