/**
  * 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)
 {
     $byDay = $this->getValues();
     foreach ($byDay as $wday) {
         $char1 = substr($wday, 0, 1);
         $cwday = strtoupper(substr($date->getWeekDayName(), 0, 2));
         if (ctype_digit($char1) || $char1 == "-" || $char1 == "+") {
             // if the first character is a digit or a plus or minus, we
             // need to check that date is a specific weekday of the month
             if (preg_match('/([+-]?)([0-9]+)([a-z]+)/i', $wday, $matches)) {
                 list($whole, $sign, $dig, $wd) = $matches;
                 // find out if this day matches the specific weekday of month
                 $xth = (int) ($sign . $dig);
                 // @todo Make sure that getXthWeekDayOfMonth doesn't need
                 // to be passed any month or date here...
                 $dtWdSpecific = $date->getXthWeekdayOfMonth($xth, $wd);
                 if ($dtWdSpecific->__toString() == $date->__toString()) {
                     return true;
                 }
             }
         } else {
             if ($wday == $cwday) {
                 return true;
             }
         }
     }
     return false;
 }
 public function testTimezoneSetsServerTimezoneToGMT()
 {
     $timezone = qCal_Timezone::factory(array("foo" => "bar", "name" => "FooBar/Assmunch", "abbreviation" => "t**s", "offsetSeconds" => "-28800"));
     // this way, our timezone component works independently of the server timezone.
     // if I can find a way to work with times without having php's functions adjust the output
     // then I will. otherwise, I'll just have to set the timezone to GMT
     // date_default_timezone_set("GMT");
     $date = gmdate("Y-m-d H:i:s", 0);
     $date = qCal_Date::gmgetdate(0);
 }
 /**
  * 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());
 }
 /**
  * Test that you can determine the amount of days in the year (usually 365, but 366 on leap-year)
  */
 public function testNumDaysInYear()
 {
     $date = new qCal_Date(2009, 4, 23);
     $this->assertEqual($date->getNumDaysInYear(), 365);
     $date2 = new qCal_Date(2008, 4, 23);
     $this->assertTrue($date2->getNumDaysInYear(), 366);
 }
 /**
  * This converts to a qCal_Date for internal storage
  */
 protected function doCast($value)
 {
     $date = qCal_Date::factory($value);
     return $date;
 }
 /**
  * Test that date data is handled right
  */
 public function testRawDate()
 {
     $value = new qCal_Value_Date('2009-04-23');
     $this->assertEqual($value->getValue(), qCal_Date::factory('2009-04-23'));
 }
 /**
  * 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;
 }
Example #8
0
 /**
  * Determine the number or Tuesdays (or whatever day of the week this date is) since the
  * beginning or end of the year.
  */
 public function getXthWeekdayOfYear($xth, $weekday = null, $year = null)
 {
     $negpos = substr($xth, 0, 1);
     if ($negpos == "+" || $negpos == "-") {
         $xth = (int) substr($xth, 1);
     } else {
         $negpos = "+";
     }
     if (is_null($weekday)) {
         $weekday = $this->getWeekday();
     }
     if (ctype_digit((string) $weekday)) {
         if (!array_key_exists($weekday, $this->weekdays)) {
             throw new qCal_Date_Exception_InvalidWeekday("\"{$weekday}\" is not a valid weekday.");
         }
     } else {
         $weekday = strtolower($weekday);
         if (!in_array($weekday, $this->weekdays)) {
             throw new qCal_Date_Exception_InvalidWeekday("\"{$weekday}\" is not a valid weekday.");
         }
         $wdays = array_flip($this->weekdays);
         $weekday = $wdays[$weekday];
     }
     if (is_null($year)) {
         $year = $this->getYear();
     }
     if (!ctype_digit((string) $year) || strlen($year) != 4) {
         throw new qCal_Date_Exception_InvalidYear("\"{$year}\" is not a valid year.");
     }
     // now find the specified day by counting either forwards or backwards to the day in question
     $firstofyear = new qCal_Date($year, 1, 1);
     $numdaysinyear = $firstofyear->isLeapYear() ? 366 : 365;
     $numweekdays = 0;
     // the number of weekdays that have occurred within the loop
     $found = false;
     // whether or not the specified day has been found
     if ($negpos == "+") {
         // count forward
         // loop over every day of every month looking for the right one
         $day = 1;
         $wday = $firstofyear->getWeekDay();
         while ($day <= $numdaysinyear) {
             // if the specified weekday == the current week day in the loop
             if ($weekday == $wday) {
                 $numweekdays++;
                 if ($numweekdays == $xth) {
                     // break out of the loop, we've found the right day! yay!
                     $found = $day;
                     break;
                 }
             }
             if ($wday == 6) {
                 $wday = 0;
             } else {
                 $wday++;
             }
             $day++;
         }
     } else {
         // count backward
         $lastofyear = new qCal_Date($year, 12, 31);
         // count forward
         // loop over every day of every month looking for the right one
         $day = $numdaysinyear;
         $wday = $lastofyear->getWeekDay();
         while ($day >= 1) {
             // if the specified weekday == the current week day in the loop
             if ($weekday == $wday) {
                 $numweekdays++;
                 if ($numweekdays == $xth) {
                     // break out of the loop, we've found the right day! yay!
                     $found = $day;
                     break;
                 }
             }
             if ($wday == 0) {
                 $wday = 6;
             } else {
                 $wday--;
             }
             $day--;
         }
     }
     // @todo: Can't use checkdate here, so find another validation method...
     if ($found) {
         $date = new qCal_Date($year, 1, $found, true);
         // takes advantage of the rollover feature :)
     } else {
         throw new qCal_DateTime_Exception_InvalidDate("You have specified an incorrect number of days for qCal_Date::getXthWeekdayOfYear()");
     }
     return $date;
 }
Example #9
0
 /**
  * @todo This is a god method that really should be split out into each
  * of the qCal_DateTime_Recur_Rule_ByXXX classes. For now I did all the logic
  * here to keep it simple and not confuse myself more than necessary.
  */
 protected function doGetRecurrences($rules, $start, $end)
 {
     // an array to store recurrences
     $recurrences = array();
     // start day, year, and month
     $sday = $start->format('d');
     $smonth = $start->format('m');
     $syear = $start->format('Y');
     // end day, year, and month
     $eday = $end->format('d');
     $emonth = $end->format('m');
     $eyear = $end->format('Y');
     // loop over years, by increment
     $year = $syear;
     while ($year <= $eyear) {
         // if byMonth is specified...
         if (count($this->byMonth())) {
             // loop over each month
             for ($month = 1; $month <= 12; $month++) {
                 // if this is the start year still and we haven't reached the start month, skip ahead
                 if ($year == $syear && $month < $smonth) {
                     continue;
                 }
                 // if this is the end year and we have passed the end month, break out of loop
                 if ($year == $eyear && $month > $emonth) {
                     break;
                 }
                 // if this is not one of the bymonths, continue as well
                 if (!in_array($month, $this->byMonth())) {
                     continue;
                 }
                 // now we need to loop over each day of the month to look for byday or bymonthday
                 $thismonth = new qCal_Date();
                 // used to determine total days in the current month
                 $thismonth->setDate($year, $month, 1);
                 $weekdays = array('MO' => 0, 'TU' => 0, 'WE' => 0, 'TH' => 0, 'FR' => 0, 'SA' => 0, 'SU' => 0);
                 // @todo For now this only allows 1SU, SU, but not -1SU (no negatives for now)
                 for ($day = 1; $day <= $thismonth->format('t'); $day++) {
                     $alreadyadded = false;
                     $date = new qCal_Date();
                     $date->setDate($year, $month, $day);
                     $date->setTime(0, 0, 0);
                     $wdname = strtoupper(substr($date->format('l'), 0, 2));
                     // keep track of how many of each day of the week have gone by
                     $weekdays[$wdname]++;
                     // if byDay is specified...
                     // @todo this is inconsistent, I don't use the getter here because of its special functionality.
                     // I need to either remove the special functionality or not use getters elsewhere in this method
                     $byday = $this->byday;
                     if (count($byday)) {
                         // by day is broken into an array of arrays like array('TH' => 0), array('FR' => 1), array('MO' => -2) etc.
                         // with zero meaning every instance of that particular day should be included and number meaning the Nth of that day
                         foreach ($byday as $val) {
                             // if at least one of this wday has gone by...
                             $num = current($val);
                             if ($weekdays[$wdname] > 0) {
                                 // check if it is the right week day and if a digit is specified (like 1SU) that it is checked as well
                                 if ($wdname == key($val) && ($weekdays[$wdname] == $num || $num == 0)) {
                                     $recurrences[] = $date;
                                     $alreadyadded = true;
                                 }
                             }
                         }
                     }
                     // if byMonthDay is specified...
                     if (count($this->byMonthDay())) {
                         foreach ($this->byMonthDay() as $mday) {
                             // only add this day if it hasn't been added already
                             if ($mday == $day && !$alreadyadded) {
                                 $recurrences[] = $date;
                             }
                         }
                     }
                     // now loop over each hour and add hours
                     if (count($this->byHour())) {
                         $hourrecurrences = array();
                         foreach ($this->byHour() as $hour) {
                             $new = new qCal_Date();
                             $new = $new->copy($date);
                             $new->setTime($hour, 0, 0);
                             $hourrecurrences[] = $new;
                         }
                     }
                     // now loop over byHours and add byMinutes
                     if (count($this->byMinute())) {
                         if (!isset($minuterecurrences)) {
                             $minuterecurrences = array();
                         }
                         foreach ($this->byMinute() as $minute) {
                             $new = new qCal_Date();
                             $new = $new->copy($date);
                             $new->setTime(0, $minute, 0);
                         }
                     }
                     // now loop over byMinutes and add bySeconds
                 }
             }
         }
         // if in the first year we don't find an instance, don't do the interval, just increment a year
         if ($year == $syear && count($recurrences)) {
             $year += $this->interval();
         } else {
             $year++;
         }
     }
     // now loop over weeks to get byWeekNo
     foreach ($recurrences as $date) {
         // pr($date->format("r"));
     }
     // exit;
     return $recurrences;
     // for bymonth, it would make the most sense to loop over each month until the specified one
     // is found. Then loop over each day to find its sub-rules.
     // for byweekno, it would make the most sense to loop over each week until the specified one
     // is found. Then apply any sub-rules (actually I'm not sure how byhour and its ilk would be applied in this situation... need to read the rfc)
 }
 public function testGetFirstAndLastDayOfMonth()
 {
     $date = new qCal_Date(2010, 1, 10);
     $first = $date->getFirstDayOfMonth();
     // will return a qCal_Date object for January 1st, 2010
     $this->assertEqual($first->__toString(), "01/01/2010");
     $date = new qCal_Date(2010, 1, 10);
     $last = $date->getLastDayOfMonth();
     // will return a qCal_Date object for January 31st, 2010
     $this->assertEqual($last->__toString(), "01/31/2010");
 }
 /**
  * How many months are there left in the year?
  */
 public function testHowManyMonthsLeftInTheYear()
 {
     $date = new qCal_Date(2010, 10, 23);
     $this->assertEqual($date->getNumMonthsUntilEndOfYear(), 2);
 }