예제 #1
0
 /**
  * Returns an array containing time zone data from VTimeZone standard/daylight instances
  *
  * @param object $vtzc, an iCalcreator calendar standard/daylight instance
  * @return array, time zone data; array before(offsetHis, offsetSec), array after(offsetHis, offsetSec, tzname)
  *
  */
 public static function expandTimezoneDates($vtzc)
 {
     $tzdates = array();
     // prepare time zone "description" to attach to each change
     $tzbefore = array();
     $tzbefore['offsetHis'] = $vtzc->getProperty('tzoffsetfrom');
     $tzbefore['offsetSec'] = ICalUtilityFunctions::_tz2offset($tzbefore['offsetHis']);
     if ('-' != substr((string) $tzbefore['offsetSec'], 0, 1) && '+' != substr((string) $tzbefore['offsetSec'], 0, 1)) {
         $tzbefore['offsetSec'] = '+' . $tzbefore['offsetSec'];
     }
     $tzafter = array();
     $tzafter['offsetHis'] = $vtzc->getProperty('tzoffsetto');
     $tzafter['offsetSec'] = ICalUtilityFunctions::_tz2offset($tzafter['offsetHis']);
     if ('-' != substr((string) $tzafter['offsetSec'], 0, 1) && '+' != substr((string) $tzafter['offsetSec'], 0, 1)) {
         $tzafter['offsetSec'] = '+' . $tzafter['offsetSec'];
     }
     if (FALSE === ($tzafter['tzname'] = $vtzc->getProperty('tzname'))) {
         $tzafter['tzname'] = $tzafter['offsetHis'];
     }
     // find out where to start from
     $dtstart = $vtzc->getProperty('dtstart');
     $dtstarttimestamp = mktime($dtstart['hour'], $dtstart['min'], $dtstart['sec'], $dtstart['month'], $dtstart['day'], $dtstart['year']);
     if (!isset($dtstart['unparsedtext'])) {
         // ??
         $dtstart['unparsedtext'] = sprintf('%04d%02d%02dT%02d%02d%02d', $dtstart['year'], $dtstart['month'], $dtstart['day'], $dtstart['hour'], $dtstart['min'], $dtstart['sec']);
     }
     if ($dtstarttimestamp == 0) {
         // it seems that the dtstart string may not have parsed correctly
         // let's set a timestamp starting from 1902, using the time part of the original string
         // so that the time will change at the right time of day
         // at worst we'll get midnight again
         $origdtstartsplit = explode('T', $dtstart['unparsedtext']);
         $dtstarttimestamp = strtotime("19020101", 0);
         $dtstarttimestamp = strtotime($origdtstartsplit[1], $dtstarttimestamp);
     }
     // the date (in dtstart and opt RDATE/RRULE) is ALWAYS LOCAL (not utc!!), adjust from 'utc' to 'local' timestamp
     $diff = -1 * $tzbefore['offsetSec'];
     $dtstarttimestamp += $diff;
     // add this (start) change to the array of changes
     $tzdates[] = array('timestamp' => $dtstarttimestamp, 'tzbefore' => $tzbefore, 'tzafter' => $tzafter);
     $datearray = getdate($dtstarttimestamp);
     // save original array to use time parts, because strtotime (used below) apparently loses the time
     $changetime = $datearray;
     // generate dates according to an RRULE line
     $rrule = $vtzc->getProperty('rrule');
     if (is_array($rrule)) {
         if ($rrule['FREQ'] == 'YEARLY') {
             // calculate transition dates starting from DTSTART
             $offsetchangetimestamp = $dtstarttimestamp;
             // calculate transition dates until 10 years in the future
             $stoptimestamp = strtotime("+10 year", time());
             // if UNTIL is set, calculate until then (however far ahead)
             if (isset($rrule['UNTIL']) && $rrule['UNTIL'] != '') {
                 $stoptimestamp = mktime($rrule['UNTIL']['hour'], $rrule['UNTIL']['min'], $rrule['UNTIL']['sec'], $rrule['UNTIL']['month'], $rrule['UNTIL']['day'], $rrule['UNTIL']['year']);
             }
             $count = 0;
             $stopcount = isset($rrule['COUNT']) ? $rrule['COUNT'] : 0;
             $daynames = array('SU' => 'Sunday', 'MO' => 'Monday', 'TU' => 'Tuesday', 'WE' => 'Wednesday', 'TH' => 'Thursday', 'FR' => 'Friday', 'SA' => 'Saturday');
             // repeat so long as we're between DTSTART and UNTIL, or we haven't prepared COUNT dates
             while ($offsetchangetimestamp < $stoptimestamp && ($stopcount == 0 || $count < $stopcount)) {
                 // break up the timestamp into its parts
                 $datearray = getdate($offsetchangetimestamp);
                 if (isset($rrule['BYMONTH']) && $rrule['BYMONTH'] != 0) {
                     // set the month
                     $datearray['mon'] = $rrule['BYMONTH'];
                 }
                 if (isset($rrule['BYMONTHDAY']) && $rrule['BYMONTHDAY'] != 0) {
                     // set specific day of month
                     $datearray['mday'] = $rrule['BYMONTHDAY'];
                 } elseif (is_array($rrule['BYDAY'])) {
                     // find the Xth WKDAY in the month
                     // the starting point for this process is the first of the month set above
                     $datearray['mday'] = 1;
                     // turn $datearray as it is now back into a timestamp
                     $offsetchangetimestamp = mktime($datearray['hours'], $datearray['minutes'], $datearray['seconds'], $datearray['mon'], $datearray['mday'], $datearray['year']);
                     if ($rrule['BYDAY'][0] > 0) {
                         // to find Xth WKDAY in month, we find last WKDAY in month before
                         // we do that by finding first WKDAY in this month and going back one week
                         // then we add X weeks (below)
                         $offsetchangetimestamp = strtotime($daynames[$rrule['BYDAY']['DAY']], $offsetchangetimestamp);
                         $offsetchangetimestamp = strtotime("-1 week", $offsetchangetimestamp);
                     } else {
                         // to find Xth WKDAY before the end of the month, we find the first WKDAY in the following month
                         // we do that by going forward one month and going to WKDAY there
                         // then we subtract X weeks (below)
                         $offsetchangetimestamp = strtotime("+1 month", $offsetchangetimestamp);
                         $offsetchangetimestamp = strtotime($daynames[$rrule['BYDAY']['DAY']], $offsetchangetimestamp);
                     }
                     // now move forward or back the appropriate number of weeks, into the month we want
                     $offsetchangetimestamp = strtotime($rrule['BYDAY'][0] . " week", $offsetchangetimestamp);
                     $datearray = getdate($offsetchangetimestamp);
                 }
                 // convert the date parts back into a timestamp, setting the time parts according to the
                 // original time data which we stored
                 $offsetchangetimestamp = mktime($changetime['hours'], $changetime['minutes'], $changetime['seconds'] + $diff, $datearray['mon'], $datearray['mday'], $datearray['year']);
                 // add this change to the array of changes
                 $tzdates[] = array('timestamp' => $offsetchangetimestamp, 'tzbefore' => $tzbefore, 'tzafter' => $tzafter);
                 // update counters (timestamp and count)
                 $offsetchangetimestamp = strtotime("+" . (isset($rrule['INTERVAL']) && $rrule['INTERVAL'] != 0 ? $rrule['INTERVAL'] : 1) . " year", $offsetchangetimestamp);
                 $count += 1;
             }
         }
     }
     // generate dates according to RDATE lines
     while ($rdates = $vtzc->getProperty('rdate')) {
         if (is_array($rdates)) {
             foreach ($rdates as $rdate) {
                 // convert the explicit change date to a timestamp
                 $offsetchangetimestamp = mktime($rdate['hour'], $rdate['min'], $rdate['sec'] + $diff, $rdate['month'], $rdate['day'], $rdate['year']);
                 // add this change to the array of changes
                 $tzdates[] = array('timestamp' => $offsetchangetimestamp, 'tzbefore' => $tzbefore, 'tzafter' => $tzafter);
             }
         }
     }
     return $tzdates;
 }
예제 #2
0
 /**
  * convert timestamp to date array, default UTC or adjusted for offset/timezone
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.15.1 - 2012-10-17
  * @param mixed   $timestamp
  * @param int     $parno
  * @param string  $wtz
  * @return array
  */
 public static function _timestamp2date($timestamp, $parno = 6, $wtz = null)
 {
     if (is_array($timestamp)) {
         $tz = isset($timestamp['tz']) ? $timestamp['tz'] : $wtz;
         $timestamp = $timestamp['timestamp'];
     }
     $tz = isset($tz) ? $tz : $wtz;
     if (empty($tz) || 'Z' == $tz || 'GMT' == strtoupper($tz)) {
         $tz = 'UTC';
     } elseif (ICalUtilityFunctions::_isOffset($tz)) {
         $offset = ICalUtilityFunctions::_tz2offset($tz);
         $tz = 'UTC';
     }
     try {
         $d = new \DateTime("@{$timestamp}");
         // set UTC date
         if (isset($offset) && 0 != $offset) {
             // adjust for offset
             $d->modify($offset . ' seconds');
         } elseif ('UTC' != $tz) {
             $d->setTimezone(new \DateTimeZone($tz));
         }
         // convert to local date
         $date = $d->format('Y-m-d-H-i-s');
         unset($d);
     } catch (Exception $e) {
         $date = date('Y-m-d-H-i-s', $timestamp);
     }
     $date = explode('-', $date);
     $output = array('year' => $date[0], 'month' => $date[1], 'day' => $date[2]);
     if (3 != $parno) {
         $output['hour'] = $date[3];
         $output['min'] = $date[4];
         $output['sec'] = $date[5];
         if ('UTC' == $tz && (!isset($offset) || 0 == $offset)) {
             $output['tz'] = 'Z';
         }
     }
     return $output;
 }