[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/ -> olson.php (source)

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * @package   moodlecore
  20   * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
  21   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22   */
  23  
  24  /**
  25   * olson_to_timezones ($filename)
  26   *
  27   * Parses the olson files for Zones and DST rules.
  28   * It updates the Moodle database with the Zones/DST rules
  29   *
  30   * @param string $filename
  31   * @return bool true/false
  32   *
  33   */
  34  function olson_to_timezones ($filename) {
  35  
  36      // Look for zone and rule information up to 10 years in the future.
  37      $maxyear = localtime(time(), true);
  38      $maxyear = $maxyear['tm_year'] + 1900 + 10;
  39  
  40      $zones = olson_simple_zone_parser($filename, $maxyear);
  41      $rules = olson_simple_rule_parser($filename, $maxyear);
  42  
  43      $mdl_zones = array();
  44  
  45      /**
  46       *** To translate the combined Zone & Rule changes
  47       *** in the Olson files to the Moodle single ruleset
  48       *** format, we need to trasverse every year and see
  49       *** if either the Zone or the relevant Rule has a
  50       *** change. It's yuck but it yields a rationalized
  51       *** set of data, which is arguably simpler.
  52       ***
  53       *** Also note that I am starting at the epoch (1970)
  54       *** because I don't think we'll see many events scheduled
  55       *** before that, anyway.
  56       ***
  57       **/
  58  
  59      foreach ($zones as $zname => $zbyyear) { // loop over zones
  60          /**
  61           *** Loop over years, only adding a rule when zone or rule
  62           *** have changed. All loops preserver the last seen vars
  63           *** until there's an explicit decision to delete them
  64           ***
  65           **/
  66  
  67          // clean the slate for a new zone
  68          $zone = NULL;
  69          $rule = NULL;
  70  
  71          //
  72          // Find the pre 1970 zone rule entries
  73          //
  74          for ($y = 1970 ; $y >= 0 ; $y--) {
  75              if (array_key_exists((string)$y, $zbyyear )) { // we have a zone entry for the year
  76                  $zone = $zbyyear[$y];
  77                  //print_object("Zone $zname pre1970 is in  $y\n");
  78                  break; // Perl's last -- get outta here
  79              }
  80          }
  81          if (!empty($zone['rule']) && array_key_exists($zone['rule'], $rules)) {
  82              $rule = NULL;
  83              for ($y = 1970 ; $y > 0 ; $y--) {
  84                  if (array_key_exists((string)$y, $rules[$zone['rule']] )) { // we have a rule entry for the year
  85                      $rule  =  $rules[$zone['rule']][$y];
  86                      //print_object("Rule $rule[name] pre1970 is $y\n");
  87                      break; // Perl's last -- get outta here
  88                  }
  89  
  90              }
  91              if (empty($rule)) {
  92                  // Colombia and a few others refer to rules before they exist
  93                  // Perhaps we should comment out this warning...
  94                  // trigger_error("Cannot find rule in $zone[rule] <= 1970");
  95                  $rule  = array();
  96              }
  97          } else {
  98              // no DST this year!
  99              $rule  = array();
 100          }
 101  
 102          // Prepare to insert the base 1970 zone+rule
 103          if (!empty($rule) && array_key_exists($zone['rule'], $rules)) {
 104              // merge the two arrays into the moodle rule
 105              unset($rule['name']); // warning: $rule must NOT be a reference!
 106              unset($rule['year']);
 107              $mdl_tz = array_merge($zone, $rule);
 108  
 109              //fix (de)activate_time (AT) field to be GMT
 110              $mdl_tz['dst_time'] = olson_parse_at($mdl_tz['dst_time'], 'set',   $mdl_tz['gmtoff']);
 111              $mdl_tz['std_time'] = olson_parse_at($mdl_tz['std_time'], 'reset', $mdl_tz['gmtoff']);
 112          } else {
 113              // just a simple zone
 114              $mdl_tz = $zone;
 115              // TODO: Add other default values here!
 116              $mdl_tz['dstoff'] = 0;
 117          }
 118  
 119          // Fix the from year to 1970
 120          $mdl_tz['year'] = 1970;
 121  
 122          // add to the array
 123          $mdl_zones[] = $mdl_tz;
 124          //print_object("Zero entry for $zone[name] added");
 125  
 126          $lasttimezone = $mdl_tz;
 127  
 128          ///
 129          /// 1971 onwards
 130          ///
 131          for ($y = 1971; $y < $maxyear ; $y++) {
 132              $changed = false;
 133              ///
 134              /// We create a "zonerule" entry if either zone or rule change...
 135              ///
 136              /// force $y to string to avoid PHP
 137              /// thinking of a positional array
 138              ///
 139              if (array_key_exists((string)$y, $zbyyear)) { // we have a zone entry for the year
 140                  $changed = true;
 141                  $zone    = $zbyyear[(string)$y];
 142              }
 143              if (!empty($zone['rule']) && array_key_exists($zone['rule'], $rules)) {
 144                  if (array_key_exists((string)$y, $rules[$zone['rule']])) {
 145                      $changed = true;
 146                      $rule    = $rules[$zone['rule']][(string)$y];
 147                  }
 148              } else {
 149                  $rule = array();
 150              }
 151  
 152              if ($changed) {
 153                  //print_object("CHANGE YEAR $y Zone $zone[name] Rule $zone[rule]\n");
 154                  if (!empty($rule)) {
 155                      // merge the two arrays into the moodle rule
 156                      unset($rule['name']);
 157                      unset($rule['year']);
 158                      $mdl_tz = array_merge($zone, $rule);
 159  
 160                      // VERY IMPORTANT!!
 161                      $mdl_tz['year'] = $y;
 162  
 163                      //fix (de)activate_time (AT) field to be GMT
 164                      $mdl_tz['dst_time'] = olson_parse_at($mdl_tz['dst_time'], 'set',   $mdl_tz['gmtoff']);
 165                      $mdl_tz['std_time'] = olson_parse_at($mdl_tz['std_time'], 'reset', $mdl_tz['gmtoff']);
 166                  } else {
 167                      // just a simple zone
 168                      $mdl_tz = $zone;
 169                  }
 170  
 171  /*
 172  if(isset($mdl_tz['dst_time']) && !strpos($mdl_tz['dst_time'], ':') || isset($mdl_tz['std_time']) &&  !strpos($mdl_tz['std_time'], ':')) {
 173      print_object($mdl_tz);
 174      print_object('---');
 175  }
 176  */
 177                  // This is the simplest way to make the != operator just below NOT take the year into account
 178                  $lasttimezone['year'] = $mdl_tz['year'];
 179  
 180                  // If not a duplicate, add and update $lasttimezone
 181                  if($lasttimezone != $mdl_tz) {
 182                      $mdl_zones[] = $lasttimezone = $mdl_tz;
 183                  }
 184              }
 185          }
 186  
 187      }
 188  
 189      /*
 190      if (function_exists('memory_get_usage')) {
 191          trigger_error("We are consuming this much memory: " . get_memory_usage());
 192      }
 193      */
 194  
 195  /// Since Moodle 1.7, rule is tzrule in DB (reserved words problem), so change it here
 196  /// after everything is calculated to be properly loaded to the timezone table.
 197  /// Pre 1.7 users won't have the old rule if updating this from moodle.org but it
 198  /// seems that such field isn't used at all by the rest of Moodle (at least I haven't
 199  /// found any use when looking for it).
 200  
 201      foreach($mdl_zones as $key=>$mdl_zone) {
 202          $mdl_zones[$key]['tzrule'] = $mdl_zones[$key]['rule'];
 203      }
 204  
 205      return $mdl_zones;
 206  }
 207  
 208  
 209  /**
 210   * olson_simple_rule_parser($filename)
 211   *
 212   * Parses the olson files for DST rules.
 213   * It's a simple implementation that simplifies some fields
 214   *
 215   * @return array a multidimensional array, or false on error
 216   *
 217   */
 218  function olson_simple_rule_parser($filename, $maxyear) {
 219  
 220      $file = fopen($filename, 'r', 0);
 221  
 222      if (empty($file)) {
 223          return false;
 224      }
 225  
 226      while ($line = fgets($file)) {
 227          // only pay attention to rules lines
 228          if(!preg_match('/^Rule\s/', $line)){
 229              continue;
 230          }
 231          $line = preg_replace('/\n$/', '',$line); // chomp
 232          $rule = preg_split('/\s+/', $line);
 233          list($discard,
 234               $name,
 235               $from,
 236               $to,
 237               $type,
 238               $in,
 239               $on,
 240               $at,
 241               $save,
 242               $letter) = $rule;
 243      }
 244  
 245      fseek($file, 0);
 246  
 247      $rules = array();
 248      while ($line = fgets($file)) {
 249          // only pay attention to rules lines
 250          if(!preg_match('/^Rule\s/', $line)){
 251              continue;
 252          }
 253          $line = preg_replace('/\n$/', '',$line); // chomp
 254          $rule = preg_split('/\s+/', $line);
 255          list($discard,
 256               $name,
 257               $from,
 258               $to,
 259               $type,
 260               $in,
 261               $on,
 262               $at,
 263               $save,
 264               $letter) = $rule;
 265  
 266          $srs = ($save === '0') ? 'reset' : 'set';
 267  
 268          if($to == 'only') {
 269              $to = $from;
 270          }
 271          else if($to == 'max') {
 272              $to = $maxyear;
 273          }
 274  
 275          for($i = $from; $i <= $to; ++$i) {
 276              $rules[$name][$i][$srs] = $rule;
 277          }
 278  
 279      }
 280  
 281      fclose($file);
 282  
 283      $months = array('jan' =>  1, 'feb' =>  2,
 284                      'mar' =>  3, 'apr' =>  4,
 285                      'may' =>  5, 'jun' =>  6,
 286                      'jul' =>  7, 'aug' =>  8,
 287                      'sep' =>  9, 'oct' => 10,
 288                      'nov' => 11, 'dec' => 12);
 289  
 290  
 291      // now reformat it a bit to match Moodle's DST table
 292      $moodle_rules = array();
 293      foreach ($rules as $rule => $rulesbyyear) {
 294          foreach ($rulesbyyear as $year => $rulesthisyear) {
 295  
 296              if(!isset($rulesthisyear['reset'])) {
 297                  // No "reset" rule. We will assume that this is somewhere in the southern hemisphere
 298                  // after a period of not using DST, otherwise it doesn't make sense at all.
 299                  // With that assumption, we can put in a fake reset e.g. on Jan 1, 12:00.
 300                  /*
 301                  print_object("no reset");
 302                  print_object($rules);
 303                  die();
 304                  */
 305                  $rulesthisyear['reset'] = array(
 306                      NULL, NULL, NULL, NULL, NULL, 'jan', 1, '12:00', '00:00', NULL
 307                  );
 308              }
 309  
 310              if(!isset($rulesthisyear['set'])) {
 311                  // No "set" rule. We will assume that this is somewhere in the southern hemisphere
 312                  // and that it begins a period of not using DST, otherwise it doesn't make sense at all.
 313                  // With that assumption, we can put in a fake set on Dec 31, 12:00, shifting time by 0 minutes.
 314                  $rulesthisyear['set'] = array(
 315                      NULL, $rulesthisyear['reset'][1], NULL, NULL, NULL, 'dec', 31, '12:00', '00:00', NULL
 316                  );
 317              }
 318  
 319              list($discard,
 320                   $name,
 321                   $from,
 322                   $to,
 323                   $type,
 324                   $in,
 325                   $on,
 326                   $at,
 327                   $save,
 328                   $letter) = $rulesthisyear['set'];
 329  
 330              $moodle_rule = array();
 331  
 332              // $save is sometimes just minutes
 333              // and othertimes HH:MM -- only
 334              // parse if relevant
 335              if (!preg_match('/^\d+$/', $save)) {
 336                  list($hours, $mins) = explode(':', $save);
 337                  $save = $hours * 60 + $mins;
 338              }
 339  
 340              // we'll parse $at later
 341              // $at = olson_parse_at($at);
 342              $in = strtolower($in);
 343              if(!isset($months[$in])) {
 344                  trigger_error('Unknown month: '.$in);
 345              }
 346  
 347              $moodle_rule['name']   = $name;
 348              $moodle_rule['year']   = $year;
 349              $moodle_rule['dstoff'] = $save; // time offset
 350  
 351              $moodle_rule['dst_month'] = $months[$in]; // the month
 352              $moodle_rule['dst_time']  = $at; // the time
 353  
 354              // Encode index and day as per Moodle's specs
 355              $on = olson_parse_on($on);
 356              $moodle_rule['dst_startday']  = $on['startday'];
 357              $moodle_rule['dst_weekday']   = $on['weekday'];
 358              $moodle_rule['dst_skipweeks'] = $on['skipweeks'];
 359  
 360              // and now the "deactivate" data
 361              list($discard,
 362                   $name,
 363                   $from,
 364                   $to,
 365                   $type,
 366                   $in,
 367                   $on,
 368                   $at,
 369                   $save,
 370                   $letter) = $rulesthisyear['reset'];
 371  
 372              // we'll parse $at later
 373              // $at = olson_parse_at($at);
 374              $in = strtolower($in);
 375              if(!isset($months[$in])) {
 376                  trigger_error('Unknown month: '.$in);
 377              }
 378  
 379              $moodle_rule['std_month'] = $months[$in]; // the month
 380              $moodle_rule['std_time']  = $at; // the time
 381  
 382              // Encode index and day as per Moodle's specs
 383              $on = olson_parse_on($on);
 384              $moodle_rule['std_startday']  = $on['startday'];
 385              $moodle_rule['std_weekday']   = $on['weekday'];
 386              $moodle_rule['std_skipweeks'] = $on['skipweeks'];
 387  
 388              $moodle_rules[$moodle_rule['name']][$moodle_rule['year']] = $moodle_rule;
 389              //print_object($moodle_rule);
 390  
 391          } // end foreach year within a rule
 392  
 393          // completed with all the entries for this rule
 394          // if the last entry has a TO other than 'max'
 395          // then we have to deal with closing the last rule
 396          //trigger_error("Rule $name ending to $to");
 397          if (!empty($to) && $to !== 'max') {
 398              // We can handle two cases for TO:
 399              // a year, or "only"
 400              $reset_rule = $moodle_rule;
 401              $reset_rule['dstoff'] = '00';
 402              if (preg_match('/^\d+$/', $to)){
 403                  $reset_rule['year'] = $to;
 404                  $moodle_rules[$reset_rule['name']][$reset_rule['year']] = $reset_rule;
 405              } elseif ($to === 'only') {
 406                  $reset_rule['year'] = $reset_rule['year'] + 1;
 407                  $moodle_rules[$reset_rule['name']][$reset_rule['year']] = $reset_rule;
 408              } else {
 409                  trigger_error("Strange value in TO $to rule field for rule $name");
 410              }
 411  
 412          } // end if $to is interesting
 413  
 414      } // end foreach rule
 415  
 416      return $moodle_rules;
 417  }
 418  
 419  /**
 420   * olson_simple_zone_parser($filename)
 421   *
 422   * Parses the olson files for zone info
 423   *
 424   * @return array a multidimensional array, or false on error
 425   *
 426   */
 427  function olson_simple_zone_parser($filename, $maxyear) {
 428  
 429      $file = fopen($filename, 'r', 0);
 430  
 431      if (empty($file)) {
 432          return false;
 433      }
 434  
 435      $zones = array();
 436      $lastzone = NULL;
 437  
 438      while ($line = fgets($file)) {
 439          // skip obvious non-zone lines
 440          if (preg_match('/^#/', $line)) {
 441              continue;
 442          }
 443          if (preg_match('/^(?:Rule|Link|Leap)/',$line)) {
 444              $lastzone = NULL; // reset lastzone
 445              continue;
 446          }
 447  
 448          // If there are blanks in the start of the line but the first non-ws character is a #,
 449          // assume it's an "inline comment". The funny thing is that this happens only during
 450          // the definition of the Rule for Europe/Athens.
 451          if(substr(trim($line), 0, 1) == '#') {
 452              continue;
 453          }
 454  
 455          /*** Notes
 456           ***
 457           *** By splitting on space, we are only keeping the
 458           *** year of the UNTIL field -- that's on purpose.
 459           ***
 460           *** The Zone lines are followed by continuation lines
 461           *** were we reuse the info from the last one seen.
 462           ***
 463           *** We are transforming "until" fields into "from" fields
 464           *** which make more sense from the Moodle perspective, so
 465           *** each initial Zone entry is "from" the year 0, and for the
 466           *** continuation lines, we shift the "until" from the previous field
 467           *** into this line's "from".
 468           ***
 469           *** If a RULES field contains a time instead of a rule we discard it
 470           *** I have no idea of how to create a DST rule out of that
 471           *** (what are the start/end times?)
 472           ***
 473           *** We remove "until" from the data we keep, but preserve
 474           *** it in $lastzone.
 475           */
 476          if (preg_match('/^Zone/', $line)) { // a new zone
 477              $line = trim($line);
 478              $line = preg_split('/\s+/', $line);
 479              $zone = array();
 480              list( $discard, // 'Zone'
 481                    $zone['name'],
 482                    $zone['gmtoff'],
 483                    $zone['rule'],
 484                    $discard // format
 485                    ) = $line;
 486              // the things we do to avoid warnings
 487              if (!empty($line[5])) {
 488                  $zone['until'] = $line[5];
 489              }
 490              $zone['year'] = '0';
 491  
 492              $zones[$zone['name']] = array();
 493  
 494          } else if (!empty($lastzone) && preg_match('/^\s+/', $line)){
 495              // looks like a credible continuation line
 496              $line = trim($line);
 497              $line = preg_split('/\s+/', $line);
 498              if (count($line) < 3) {
 499                  $lastzone = NULL;
 500                  continue;
 501              }
 502              // retrieve info from the lastzone
 503              $zone = $lastzone;
 504              $zone['year'] = $zone['until'];
 505              // overwrite with current data
 506              list(
 507                    $zone['gmtoff'],
 508                    $zone['rule'],
 509                    $discard // format
 510                    ) = $line;
 511              // the things we do to avoid warnings
 512              if (!empty($line[3])) {
 513                  $zone['until'] = $line[3];
 514              }
 515  
 516          } else {
 517              $lastzone = NULL;
 518              continue;
 519          }
 520  
 521          // tidy up, we're done
 522          // perhaps we should insert in the DB at this stage?
 523          $lastzone = $zone;
 524          unset($zone['until']);
 525          $zone['gmtoff'] = olson_parse_offset($zone['gmtoff']);
 526          if ($zone['rule'] === '-') { // cleanup empty rules
 527              $zone['rule'] = '';
 528          }
 529          if (preg_match('/:/',$zone['rule'])) {
 530              // we are not handling direct SAVE rules here
 531              // discard it
 532              $zone['rule'] = '';
 533          }
 534  
 535          $zones[$zone['name']][(string)$zone['year']] = $zone;
 536      }
 537  
 538      return $zones;
 539  }
 540  
 541  /**
 542   * olson_parse_offset($offset)
 543   *
 544   * parses time offsets from the GMTOFF and SAVE
 545   * fields into +/-MINUTES
 546   *
 547   * @return int
 548   */
 549  function olson_parse_offset ($offset) {
 550      $offset = trim($offset);
 551  
 552      // perhaps it's just minutes
 553      if (preg_match('/^(-?)(\d*)$/', $offset)) {
 554          return intval($offset);
 555      }
 556      // (-)hours:minutes(:seconds)
 557      if (preg_match('/^(-?)(\d*):(\d+)/', $offset, $matches)) {
 558          // we are happy to discard the seconds
 559          $sign    = $matches[1];
 560          $hours   = intval($matches[2]);
 561          $seconds = intval($matches[3]);
 562          $offset  = $sign . ($hours*60 + $seconds);
 563          return intval($offset);
 564      }
 565  
 566      trigger_error('Strange time format in olson_parse_offset() ' .$offset);
 567      return 0;
 568  
 569  }
 570  
 571  
 572  /**
 573   * olson_parse_on_($on)
 574   *
 575   * see `man zic`. This function translates the following formats
 576   * 5        the fifth of the month
 577   * lastSun  the last Sunday in the month
 578   * lastMon  the last Monday in the month
 579   * Sun>=8   first Sunday on or after the eighth
 580   * Sun<=25  last Sunday on or before the 25th
 581   *
 582   * to a moodle friendly format. Returns an array with:
 583   *
 584   * startday: the day of the month that we start counting from.
 585   *           if negative, it means we start from that day and
 586   *           count backwards. since -1 would be meaningless,
 587   *           it means "end of month and backwards".
 588   * weekday:  the day of the week that we must find. we will
 589   *           scan days from the startday until we find the
 590   *           first such weekday. 0...6 = Sun...Sat.
 591   *           -1 means that any day of the week will do,
 592   *           effectively ending the search on startday.
 593   * skipweeks:after finding our end day as outlined above,
 594   *           skip this many weeks. this enables us to find
 595   *           "the second sunday >= 10". usually will be 0.
 596   */
 597  function olson_parse_on ($on) {
 598  
 599      $rule = array();
 600      $days = array('sun' => 0, 'mon' => 1,
 601                    'tue' => 2, 'wed' => 3,
 602                    'thu' => 4, 'fri' => 5,
 603                    'sat' => 6);
 604  
 605      if(is_numeric($on)) {
 606          $rule['startday']  = intval($on); // Start searching from that day
 607          $rule['weekday']   = -1;          // ...and stop there, no matter what weekday
 608          $rule['skipweeks'] = 0;           // Don't skip any weeks.
 609      }
 610      else {
 611          $on = strtolower($on);
 612          if(substr($on, 0, 4) == 'last') {
 613              // e.g. lastSun
 614              if(!isset($days[substr($on, 4)])) {
 615                  trigger_error('Unknown last weekday: '.substr($on, 4));
 616              }
 617              else {
 618                  $rule['startday']  = -1;                    // Start from end of month
 619                  $rule['weekday']   = $days[substr($on, 4)]; // Find the first such weekday
 620                  $rule['skipweeks'] = 0;                     // Don't skip any weeks.
 621              }
 622          }
 623          else if(substr($on, 3, 2) == '>=') {
 624              // e.g. Sun>=8
 625              if(!isset($days[substr($on, 0, 3)])) {
 626                  trigger_error('Unknown >= weekday: '.substr($on, 0, 3));
 627              }
 628              else {
 629                  $rule['startday']  = intval(substr($on, 5));   // Start from that day of the month
 630                  $rule['weekday']   = $days[substr($on, 0, 3)]; // Find the first such weekday
 631                  $rule['skipweeks'] = 0;                        // Don't skip any weeks.
 632              }
 633          }
 634          else if(substr($on, 3, 2) == '<=') {
 635              // e.g. Sun<=25
 636              if(!isset($days[substr($on, 0, 3)])) {
 637                  trigger_error('Unknown <= weekday: '.substr($on, 0, 3));
 638              }
 639              else {
 640                  $rule['startday']  = -intval(substr($on, 5));  // Start from that day of the month; COUNT BACKWARDS (minus sign)
 641                  $rule['weekday']   = $days[substr($on, 0, 3)]; // Find the first such weekday
 642                  $rule['skipweeks'] = 0;                        // Don't skip any weeks.
 643              }
 644          }
 645          else {
 646              trigger_error('unknown on '.$on);
 647          }
 648      }
 649      return $rule;
 650  }
 651  
 652  
 653  /**
 654   * olson_parse_at($at, $set, $gmtoffset)
 655   *
 656   * see `man zic`. This function translates
 657   *
 658   *      2        time in hours
 659   *      2:00     time in hours and minutes
 660   *     15:00     24-hour format time (for times after noon)
 661   *      1:28:14  time in hours, minutes, and seconds
 662   *
 663   *  Any of these forms may be followed by the letter w if the given
 664   *  time is local "wall clock" time, s if the given time  is  local
 665   *  "standard"  time, or u (or g or z) if the given time is univer-
 666   *  sal time; in the absence of an indicator, wall  clock  time  is
 667   *  assumed.
 668   *
 669   * @return string a moodle friendly $at, in GMT, which is what Moodle wants
 670   *
 671   *
 672   */
 673  function olson_parse_at ($at, $set = 'set', $gmtoffset) {
 674  
 675      // find the time "signature";
 676      $sig = '';
 677      if (preg_match('/[ugzs]$/', $at, $matches)) {
 678          $sig = $matches[0];
 679          $at  = substr($at, 0, strlen($at)-1); // chop
 680      }
 681  
 682      $at = (strpos($at, ':') === false) ? $at . ':0' : $at;
 683      list($hours, $mins) = explode(':', $at);
 684  
 685      // GMT -- return as is!
 686      if ( !empty($sig) && ( $sig === 'u'
 687                             || $sig === 'g'
 688                             || $sig === 'z'    )) {
 689          return $at;
 690      }
 691  
 692      // Wall clock
 693      if (empty($sig) || $sig === 'w') {
 694          if ($set !== 'set'){ // wall clock is on DST, assume by 1hr
 695              $hours = $hours-1;
 696          }
 697          $sig = 's';
 698      }
 699  
 700      // Standard time
 701      if (!empty($sig) && $sig === 's') {
 702          $mins = $mins + $hours*60 + $gmtoffset;
 703          $hours = $mins / 60;
 704          $hours = (int)$hours;
 705          $mins  = abs($mins % 60);
 706          return sprintf('%02d:%02d', $hours, $mins);
 707      }
 708  
 709      trigger_error('unhandled case - AT flag is ' . $matches[0]);
 710  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1