<?php
/**
 * By Greg MacLellan, Feb 13, 2005
 * based on work by heymeadows@yahoo.com
*/
/*

todo:

ideas:
- moon phases (http://www.zend.com/codex.php?id=830&single=1)

*/


/** A single holiday */
class Holiday {
    var 
$_name;
    var 
$_date;
    var 
$_type;
    
    
/** Creates a new holiday object.
     * @param  string  $name   The name of the holiday
     * @param  date    $date   The date (unix timestamp, midnight) of the
     *                         holiday
     * @param  mixed   $type   An optional parameter for internal use, ie
     *                         statutory holidays vs 'special' days
     */
    
function Holiday($name$date$type 0) {
        
$this->_name $name;
        
$this->_date $date;
        
$this->_type $type;
    }
}

/** Creates a list of holidays
 * 
 * The default holiday list is for Canada
 *
 * @author Greg MacLellan (greg@gregmaclellan.com)
 */
class Holidays {
    var 
$holidays = array();
    
    
/** Creates the Holidays object, and initalizes holidays for a given year
     * @param  int  $year  The year in which to create holidays. If no year is given
     *                     (value is null), then no holidays are initalized
     */
    
function Holidays($year null) {
        if (
$year) {
            
$this->addHolidays($year);
        }
    }
    
    
/** Gets a holiday for a given timestamp. The timestamp should be midnight of
     * the requested day (ie, mktime(0,0,0, $month, $day, $year) )
     * @param int  $date  The day to get holidays for
     * @return  The Holiday object, or false if no holiday occurs that day
     */
    
function getHoliday($date) {
        return (
$this->holidays[$date] ? $this->holidays[$date] : false); 
    }
    
    
/** Adds a list of pre-defined holidays for the given year.
     * This can be usful to add more than one years worth of holidays to the list
     */
    
function addHolidays($year) {
        
$this->addHoliday(new Holiday("New Year's Day"mktime(0,0,011$year), 1));            // January 1st
        
$this->addHoliday(new Holiday("Groundhog Day"mktime(0,0,022$year), 0));            // february 2nd
        
$this->addHoliday(new Holiday("Valentine's Day"mktime(0,0,0214$year), 0));            // february 14th
        
$this->addHoliday(new Holiday("St. Patrick's Day"mktime(0,0,0317$year), 0));        // march 17th
        
$this->addHoliday(new Holiday("Good Friday"easter_date($year)-(86400*2), 1));            // friday before easter
        
$this->addHoliday(new Holiday("Easter"easter_date($year), 1));                    // Sunday after the first full moon which falls on or after the Spring Equinox
        
$this->addHoliday(new Holiday("Easter Monday"easter_date($year)+864001));            // monday after easter
        
$this->addHoliday(new Holiday("Mother's Day"$this->ordinalDay(2'Sun'5$year), 0));        // 2nd sunday of may
        
        
$this->addHoliday(new Holiday("Canada Day"mktime(0,0,071$year), 1));                // july 1st
        
if (date("w"mktime(0,0,071$year)) == 0) {
            
// if July 1st is a Sunday, then Canada Day holiday is july 2
            
$this->addHoliday(new Holiday("Canada Day (Holiday)"mktime(0,0,072$year), 1));    // july 2nd
        
}
        
        
$this->addHoliday(new Holiday("Father's Day"$this->ordinalDay(3'Sun'6$year), 0));        // 3rd sunday of june
        
$this->addHoliday(new Holiday("Thanksgiving"$this->ordinalDay(2'Mon'10$year), 1));     // 2nd monday of october
        
$this->addHoliday(new Holiday("Labour Day"$this->ordinalDay(1'Mon'9$year), 0));        // 1st monday of september
        
$this->addHoliday(new Holiday("Rememberance Day"mktime(0,0,01111$year), 0));        // november 11th
        
$this->addHoliday(new Holiday("Christmas"mktime(0,0,01225$year), 1));            // december 24th
        
$this->addHoliday(new Holiday("Boxing Day"mktime(0,0,01226$year), 1));            // december 25th
    
}
    
    
/** Adds a single holiday object to the list of holidays
     * @param Holiday  $holiday  The holiday object to add
     */
    
function addHoliday($holiday) {
        
$this->holidays[$holiday->_date] = $holiday;
    }
    
    function 
ordinalDay($ord$day$month$year) { 
        
// ordinalDay returns date of the $ord $day of $month. 
        // For example ordinalDay(3, 'Sun', 5, 2001) returns the 
        // date of the 3rd Sunday of May (ie. Mother's Day). 
        // 
        // Note: $day must be the 3 char abbr. for the day, as 
        //       given by date("D"); 
        // 
        // By: heymeadows@yahoo.com
        // optimized a bit by greg maclellan 
        
        
$firstOfMonth mktime(0,0,0,$month,1,$year); 
        
$lastOfMonth  $firstOfMonth date("t"$firstOfMonth) * 86400
        
$dayOccurs 0
        
        for (
$i $firstOfMonth$i $lastOfMonth $i += 86400) { 
            if (
date("D"$i) == $day) { 
                
$dayOccurs++; 
                if (
$dayOccurs == $ord) { 
                    
$ordDay $i;
                }  
               }
        }
        return 
$ordDay
    }
    
    
}

?>