/**
  * How many days from the beginning or end of the month or year it is
  * (ie: February 15th is the 46th day of the year and 13 days from the end of the month)
  */
 public function testHowManyDaysFromTheBeginningOrEndOfTheMonthOrYearItIs()
 {
     /**
      * Year
      */
     // days 'til end of year
     $date = new qCal_Date(2010, 1, 15, "GMT");
     // mom's birthday!
     $this->assertEqual($date->getYearDay(), 14);
     // year day starts at zero
     $this->assertEqual($date->getYearDay(true), 15);
     // pass true to the method and it will start from one
     $this->assertEqual($date->getNumDaysUntilEndOfYear(), 350);
     $date2 = new qCal_Date(2010, 12, 25);
     // jesus's birthday (not really, but w/e)!
     $this->assertEqual($date2->getNumDaysUntilEndOfYear(), 6);
     /**
      * Month
      */
     $date3 = new qCal_Date(2010, 3, 20);
     // mom and dady's anniversary!
     $this->assertEqual($date3->getDay(), 20);
     // this one is pretty obvious...
     $this->assertEqual($date3->getNumDaysUntilEndOfMonth(), 11);
 }
 /**
  * Check a qCal_Date object to see if it falls within the rules specified
  * when this object was created (or added later actually).
  * @param qCal_Date The date that you want to check 
  * @return boolean True if the date falls within the ruleset
  * @access public
  */
 public function checkDate(qCal_Date $date)
 {
     return (bool) in_array($date->getDay(), $this->getValues());
 }
 /**
  * The date object has many getters which allow for you to determine things like day of the week,
  * day of the year, etc. The following tests those getters.
  */
 public function testGetters()
 {
     $date = new qCal_Date(2009, 4, 23);
     /**
      * Month
      */
     $this->assertEqual($date->getMonth(), 4);
     $this->assertEqual($date->getMonthName(), "April");
     $this->assertEqual($date->getNumDaysInMonth(), 30);
     /**
      * Day
      */
     $this->assertEqual($date->getDay(), 23);
     $this->assertEqual($date->getYearDay(), 112);
     $this->assertEqual($date->getFirstDayOfMonth()->__toString(), "04/01/2009");
     $this->assertEqual($date->getFirstDayOfMonth()->format("l"), "Wednesday");
     $this->assertEqual($date->getLastDayOfMonth()->__toString(), "04/30/2009");
     $this->assertEqual($date->getLastDayOfMonth()->format("l"), "Thursday");
     // find the xth weekday (mon-sun) of the month
     $this->assertEqual($date->getXthWeekdayOfMonth(2)->__toString(), "04/09/2009");
     // find the second Thursday of the month (Because 4/23/2009 was on a Thursday, the weekday defaults to that. The year defaults to 2009 for basically the same reason)
     $this->assertEqual($date->getXthWeekdayOfMonth(2, "Monday")->__toString(), "04/13/2009");
     // find the second monday of the month (month defaults to april because that's what $date is currently set to)
     $this->assertEqual($date->getXthWeekdayOfMonth(2, "Monday", "January")->__toString(), "01/12/2009");
     // find the second monday in January (year defaults to 2009)
     $this->assertEqual($date->getXthWeekdayOfMonth(2, "Monday", "January", 2008)->__toString(), "01/14/2008");
     // find the second Monday in January, 2008
     // now try negatives and positives
     $this->assertEqual($date->getXthWeekdayOfMonth(-2)->__toString(), "04/23/2009");
     // get the second to last Thursday of the month
     $this->assertEqual($date->getXthWeekdayOfMonth("-2")->__toString(), "04/23/2009");
     // get the second to last Thursday of the month
     $this->assertEqual($date->getXthWeekdayOfMonth(+2)->__toString(), "04/09/2009");
     // surprisingly, this works... interesting...
     $this->assertEqual($date->getXthWeekdayOfMonth("+2")->__toString(), "04/09/2009");
     // we can also use numbers instead of spelling out the names of weekdays and months. For the weekday part, use 0 for Sunday through 6 for Saturday (the same as PHP's date function's "w" metacharacter)
     $this->assertEqual($date->getXthWeekdayOfMonth(2, 1)->__toString(), "04/13/2009");
     // second monday
     $this->assertEqual($date->getXthWeekdayOfMonth(2, 1, 1)->__toString(), "01/12/2009");
     // second monday in january
     $this->assertEqual($date->getXthWeekdayOfMonth(-2, 1)->__toString(), "04/20/2009");
     // second to last monday in april
     /**
      * Year
      */
     $this->assertEqual($date->getYear(), 2009);
     /**
      * Week
      */
     $this->assertEqual($date->getWeekDay(), 4);
     $this->assertEqual($date->getWeekDayName(), "Thursday");
     $this->assertEqual($date->getWeekOfYear(), 17);
     /**
      * Unix Timestamp
      */
     $this->assertEqual($date->getUnixTimestamp(), gmmktime(0, 0, 0, 4, 23, 2009));
 }
 /**
  * Provided a date/time object, use this recurrence's rules to determine
  * all of the recurrence times for the date and return them in an array.
  * @param qCal_Date The date object to find time recurrences for
  * @return array A list of time recurrences for the specified date/time
  * @access protected
  * @todo I don't really like the way this is done. Definitely a code smell here.
  * Each of the rules should do their own logic. Something like:
  * 	$seconds = $bySecond->getTimeInstances();
  * 	$minutes = $byMinute->getTimeInstances($seconds);
  * 	$hours = $byHour->getTimeInstances($minutes);
  */
 protected function findTimeRecurrences(qCal_Date $date)
 {
     // find all of the bySeconds
     $seconds = array();
     if ($this->hasRule('qCal_DateTime_Recur_Rule_BySecond')) {
         $seconds = $this->getRule('qCal_DateTime_Recur_Rule_BySecond')->getValues();
         sort($seconds);
     } else {
         $seconds = array($this->getStart()->getTime()->getSecond());
     }
     // find all of the byMinutes
     $minutes = array();
     if ($this->hasRule('qCal_DateTime_Recur_Rule_ByMinute')) {
         $minutesRules = $this->getRule('qCal_DateTime_Recur_Rule_ByMinute')->getValues();
         sort($minutesRules);
     } else {
         $minutesRules = array($this->getStart()->getTime()->getMinute());
     }
     foreach ($minutesRules as $minute) {
         $minutes[$minute] = $seconds;
     }
     // find all of the byHours
     $hours = array();
     if ($this->hasRule('qCal_DateTime_Recur_Rule_ByHour')) {
         $hoursRules = $this->getRule('qCal_DateTime_Recur_Rule_ByHour')->getValues();
         sort($hoursRules);
     } else {
         $hoursRules = array($this->getStart()->getTime()->getHour());
     }
     foreach ($hoursRules as $hour) {
         $hours[$hour] = $minutes;
     }
     // create an array to store times
     $times = array();
     foreach ($hours as $hour => $minutes) {
         foreach ($minutes as $minute => $seconds) {
             foreach ($seconds as $second) {
                 try {
                     // try to build a date/time object
                     $datetime = new qCal_DateTime($date->getYear(), $date->getMonth(), $date->getDay(), $hour, $minute, $second);
                     $times[$datetime->format('YmdHis')] = $datetime;
                 } catch (qCal_DateTime_Exception_InvalidTime $e) {
                     // if the date/time object instantiation fails, this exception will be thrown
                     // @todo Recover from this error and report it. Maybe catch the error and pass it to a log or something?
                     // qCal_Log::logException($e, get_class($this));
                     throw $e;
                 }
             }
         }
     }
     return $times;
 }