[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/lib/ -> olson.php (source)

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


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7