[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/SimplePie/src/Parse/ -> Date.php (source)

   1  <?php
   2  
   3  // SPDX-FileCopyrightText: 2004-2023 Ryan Parman, Sam Sneddon, Ryan McCue
   4  // SPDX-License-Identifier: BSD-3-Clause
   5  
   6  declare(strict_types=1);
   7  
   8  namespace SimplePie\Parse;
   9  
  10  /**
  11   * Date Parser
  12   */
  13  class Date
  14  {
  15      /**
  16       * Input data
  17       *
  18       * @access protected
  19       * @var string
  20       */
  21      public $date;
  22  
  23      /**
  24       * List of days, calendar day name => ordinal day number in the week
  25       *
  26       * @access protected
  27       * @var array<string, int<1,7>>
  28       */
  29      public $day = [
  30          // English
  31          'mon' => 1,
  32          'monday' => 1,
  33          'tue' => 2,
  34          'tuesday' => 2,
  35          'wed' => 3,
  36          'wednesday' => 3,
  37          'thu' => 4,
  38          'thursday' => 4,
  39          'fri' => 5,
  40          'friday' => 5,
  41          'sat' => 6,
  42          'saturday' => 6,
  43          'sun' => 7,
  44          'sunday' => 7,
  45          // Dutch
  46          'maandag' => 1,
  47          'dinsdag' => 2,
  48          'woensdag' => 3,
  49          'donderdag' => 4,
  50          'vrijdag' => 5,
  51          'zaterdag' => 6,
  52          'zondag' => 7,
  53          // French
  54          'lundi' => 1,
  55          'mardi' => 2,
  56          'mercredi' => 3,
  57          'jeudi' => 4,
  58          'vendredi' => 5,
  59          'samedi' => 6,
  60          'dimanche' => 7,
  61          // German
  62          'montag' => 1,
  63          'mo' => 1,
  64          'dienstag' => 2,
  65          'di' => 2,
  66          'mittwoch' => 3,
  67          'mi' => 3,
  68          'donnerstag' => 4,
  69          'do' => 4,
  70          'freitag' => 5,
  71          'fr' => 5,
  72          'samstag' => 6,
  73          'sa' => 6,
  74          'sonnabend' => 6,
  75          // AFAIK no short form for sonnabend
  76          'so' => 7,
  77          'sonntag' => 7,
  78          // Italian
  79          'lunedì' => 1,
  80          'martedì' => 2,
  81          'mercoledì' => 3,
  82          'giovedì' => 4,
  83          'venerdì' => 5,
  84          'sabato' => 6,
  85          'domenica' => 7,
  86          // Spanish
  87          'lunes' => 1,
  88          'martes' => 2,
  89          'miércoles' => 3,
  90          'jueves' => 4,
  91          'viernes' => 5,
  92          'sábado' => 6,
  93          'domingo' => 7,
  94          // Finnish
  95          'maanantai' => 1,
  96          'tiistai' => 2,
  97          'keskiviikko' => 3,
  98          'torstai' => 4,
  99          'perjantai' => 5,
 100          'lauantai' => 6,
 101          'sunnuntai' => 7,
 102          // Hungarian
 103          'hétfő' => 1,
 104          'kedd' => 2,
 105          'szerda' => 3,
 106          'csütörtok' => 4,
 107          'péntek' => 5,
 108          'szombat' => 6,
 109          'vasárnap' => 7,
 110          // Greek
 111          'Δευ' => 1,
 112          'Τρι' => 2,
 113          'Τετ' => 3,
 114          'Πεμ' => 4,
 115          'Παρ' => 5,
 116          'Σαβ' => 6,
 117          'Κυρ' => 7,
 118          // Russian
 119          'Пн.' => 1,
 120          'Вт.' => 2,
 121          'Ср.' => 3,
 122          'Чт.' => 4,
 123          'Пт.' => 5,
 124          'Сб.' => 6,
 125          'Вс.' => 7,
 126      ];
 127  
 128      /**
 129       * List of months, calendar month name => calendar month number
 130       *
 131       * @access protected
 132       * @var array<string, int<1,12>>
 133       */
 134      public $month = [
 135          // English
 136          'jan' => 1,
 137          'january' => 1,
 138          'feb' => 2,
 139          'february' => 2,
 140          'mar' => 3,
 141          'march' => 3,
 142          'apr' => 4,
 143          'april' => 4,
 144          'may' => 5,
 145          // No long form of May
 146          'jun' => 6,
 147          'june' => 6,
 148          'jul' => 7,
 149          'july' => 7,
 150          'aug' => 8,
 151          'august' => 8,
 152          'sep' => 9,
 153          'september' => 9,
 154          'oct' => 10,
 155          'october' => 10,
 156          'nov' => 11,
 157          'november' => 11,
 158          'dec' => 12,
 159          'december' => 12,
 160          // Dutch
 161          'januari' => 1,
 162          'februari' => 2,
 163          'maart' => 3,
 164          // 'april' => 4,
 165          'mei' => 5,
 166          'juni' => 6,
 167          'juli' => 7,
 168          'augustus' => 8,
 169          // 'september' => 9,
 170          'oktober' => 10,
 171          // 'november' => 11,
 172          // 'december' => 12,
 173          // French
 174          'janvier' => 1,
 175          'février' => 2,
 176          'mars' => 3,
 177          'avril' => 4,
 178          'mai' => 5,
 179          'juin' => 6,
 180          'juillet' => 7,
 181          'août' => 8,
 182          'septembre' => 9,
 183          'octobre' => 10,
 184          'novembre' => 11,
 185          'décembre' => 12,
 186          // German
 187          'januar' => 1,
 188          // 'jan' => 1,
 189          'februar' => 2,
 190          // 'feb' => 2,
 191          'märz' => 3,
 192          'mär' => 3,
 193          // 'april' => 4,
 194          // 'apr' => 4,
 195          // 'mai' => 5, // no short form for may
 196          // 'juni' => 6,
 197          // 'jun' => 6,
 198          // 'juli' => 7,
 199          // 'jul' => 7,
 200          // 'august' => 8,
 201          // 'aug' => 8,
 202          // 'september' => 9,
 203          // 'sep' => 9,
 204          // 'oktober' => 10,
 205          'okt' => 10,
 206          // 'november' => 11,
 207          // 'nov' => 11,
 208          'dezember' => 12,
 209          'dez' => 12,
 210          // Italian
 211          'gennaio' => 1,
 212          'febbraio' => 2,
 213          'marzo' => 3,
 214          'aprile' => 4,
 215          'maggio' => 5,
 216          'giugno' => 6,
 217          'luglio' => 7,
 218          'agosto' => 8,
 219          'settembre' => 9,
 220          'ottobre' => 10,
 221          // 'novembre' => 11,
 222          'dicembre' => 12,
 223          // Spanish
 224          'enero' => 1,
 225          'febrero' => 2,
 226          // 'marzo' => 3,
 227          'abril' => 4,
 228          'mayo' => 5,
 229          'junio' => 6,
 230          'julio' => 7,
 231          // 'agosto' => 8,
 232          'septiembre' => 9,
 233          'setiembre' => 9,
 234          'octubre' => 10,
 235          'noviembre' => 11,
 236          'diciembre' => 12,
 237          // Finnish
 238          'tammikuu' => 1,
 239          'helmikuu' => 2,
 240          'maaliskuu' => 3,
 241          'huhtikuu' => 4,
 242          'toukokuu' => 5,
 243          'kesäkuu' => 6,
 244          'heinäkuu' => 7,
 245          'elokuu' => 8,
 246          'suuskuu' => 9,
 247          'lokakuu' => 10,
 248          'marras' => 11,
 249          'joulukuu' => 12,
 250          // Hungarian
 251          'január' => 1,
 252          'február' => 2,
 253          'március' => 3,
 254          'április' => 4,
 255          'május' => 5,
 256          'június' => 6,
 257          'július' => 7,
 258          'augusztus' => 8,
 259          'szeptember' => 9,
 260          'október' => 10,
 261          // 'november' => 11,
 262          // 'december' => 12,
 263          // Greek
 264          'Ιαν' => 1,
 265          'Φεβ' => 2,
 266          'Μάώ' => 3,
 267          'Μαώ' => 3,
 268          'Απρ' => 4,
 269          'Μάι' => 5,
 270          'Μαϊ' => 5,
 271          'Μαι' => 5,
 272          'Ιούν' => 6,
 273          'Ιον' => 6,
 274          'Ιούλ' => 7,
 275          'Ιολ' => 7,
 276          'Αύγ' => 8,
 277          'Αυγ' => 8,
 278          'Σεπ' => 9,
 279          'Οκτ' => 10,
 280          'Νοέ' => 11,
 281          'Δεκ' => 12,
 282          // Russian
 283          'Янв' => 1,
 284          'января' => 1,
 285          'Фев' => 2,
 286          'февраля' => 2,
 287          'Мар' => 3,
 288          'марта' => 3,
 289          'Апр' => 4,
 290          'апреля' => 4,
 291          'Май' => 5,
 292          'мая' => 5,
 293          'Июн' => 6,
 294          'июня' => 6,
 295          'Июл' => 7,
 296          'июля' => 7,
 297          'Авг' => 8,
 298          'августа' => 8,
 299          'Сен' => 9,
 300          'сентября' => 9,
 301          'Окт' => 10,
 302          'октября' => 10,
 303          'Ноя' => 11,
 304          'ноября' => 11,
 305          'Дек' => 12,
 306          'декабря' => 12,
 307  
 308      ];
 309  
 310      /**
 311       * List of timezones, abbreviation => offset from UTC
 312       *
 313       * @access protected
 314       * @var array<string, int>
 315       */
 316      public $timezone = [
 317          'ACDT' => 37800,
 318          'ACIT' => 28800,
 319          'ACST' => 34200,
 320          'ACT' => -18000,
 321          'ACWDT' => 35100,
 322          'ACWST' => 31500,
 323          'AEDT' => 39600,
 324          'AEST' => 36000,
 325          'AFT' => 16200,
 326          'AKDT' => -28800,
 327          'AKST' => -32400,
 328          'AMDT' => 18000,
 329          'AMT' => -14400,
 330          'ANAST' => 46800,
 331          'ANAT' => 43200,
 332          'ART' => -10800,
 333          'AZOST' => -3600,
 334          'AZST' => 18000,
 335          'AZT' => 14400,
 336          'BIOT' => 21600,
 337          'BIT' => -43200,
 338          'BOT' => -14400,
 339          'BRST' => -7200,
 340          'BRT' => -10800,
 341          'BST' => 3600,
 342          'BTT' => 21600,
 343          'CAST' => 18000,
 344          'CAT' => 7200,
 345          'CCT' => 23400,
 346          'CDT' => -18000,
 347          'CEDT' => 7200,
 348          'CEST' => 7200,
 349          'CET' => 3600,
 350          'CGST' => -7200,
 351          'CGT' => -10800,
 352          'CHADT' => 49500,
 353          'CHAST' => 45900,
 354          'CIST' => -28800,
 355          'CKT' => -36000,
 356          'CLDT' => -10800,
 357          'CLST' => -14400,
 358          'COT' => -18000,
 359          'CST' => -21600,
 360          'CVT' => -3600,
 361          'CXT' => 25200,
 362          'DAVT' => 25200,
 363          'DTAT' => 36000,
 364          'EADT' => -18000,
 365          'EAST' => -21600,
 366          'EAT' => 10800,
 367          'ECT' => -18000,
 368          'EDT' => -14400,
 369          'EEST' => 10800,
 370          'EET' => 7200,
 371          'EGT' => -3600,
 372          'EKST' => 21600,
 373          'EST' => -18000,
 374          'FJT' => 43200,
 375          'FKDT' => -10800,
 376          'FKST' => -14400,
 377          'FNT' => -7200,
 378          'GALT' => -21600,
 379          'GEDT' => 14400,
 380          'GEST' => 10800,
 381          'GFT' => -10800,
 382          'GILT' => 43200,
 383          'GIT' => -32400,
 384          'GST' => 14400,
 385          // 'GST' => -7200,
 386          'GYT' => -14400,
 387          'HAA' => -10800,
 388          'HAC' => -18000,
 389          'HADT' => -32400,
 390          'HAE' => -14400,
 391          'HAP' => -25200,
 392          'HAR' => -21600,
 393          'HAST' => -36000,
 394          'HAT' => -9000,
 395          'HAY' => -28800,
 396          'HKST' => 28800,
 397          'HMT' => 18000,
 398          'HNA' => -14400,
 399          'HNC' => -21600,
 400          'HNE' => -18000,
 401          'HNP' => -28800,
 402          'HNR' => -25200,
 403          'HNT' => -12600,
 404          'HNY' => -32400,
 405          'IRDT' => 16200,
 406          'IRKST' => 32400,
 407          'IRKT' => 28800,
 408          'IRST' => 12600,
 409          'JFDT' => -10800,
 410          'JFST' => -14400,
 411          'JST' => 32400,
 412          'KGST' => 21600,
 413          'KGT' => 18000,
 414          'KOST' => 39600,
 415          'KOVST' => 28800,
 416          'KOVT' => 25200,
 417          'KRAST' => 28800,
 418          'KRAT' => 25200,
 419          'KST' => 32400,
 420          'LHDT' => 39600,
 421          'LHST' => 37800,
 422          'LINT' => 50400,
 423          'LKT' => 21600,
 424          'MAGST' => 43200,
 425          'MAGT' => 39600,
 426          'MAWT' => 21600,
 427          'MDT' => -21600,
 428          'MESZ' => 7200,
 429          'MEZ' => 3600,
 430          'MHT' => 43200,
 431          'MIT' => -34200,
 432          'MNST' => 32400,
 433          'MSDT' => 14400,
 434          'MSST' => 10800,
 435          'MST' => -25200,
 436          'MUT' => 14400,
 437          'MVT' => 18000,
 438          'MYT' => 28800,
 439          'NCT' => 39600,
 440          'NDT' => -9000,
 441          'NFT' => 41400,
 442          'NMIT' => 36000,
 443          'NOVST' => 25200,
 444          'NOVT' => 21600,
 445          'NPT' => 20700,
 446          'NRT' => 43200,
 447          'NST' => -12600,
 448          'NUT' => -39600,
 449          'NZDT' => 46800,
 450          'NZST' => 43200,
 451          'OMSST' => 25200,
 452          'OMST' => 21600,
 453          'PDT' => -25200,
 454          'PET' => -18000,
 455          'PETST' => 46800,
 456          'PETT' => 43200,
 457          'PGT' => 36000,
 458          'PHOT' => 46800,
 459          'PHT' => 28800,
 460          'PKT' => 18000,
 461          'PMDT' => -7200,
 462          'PMST' => -10800,
 463          'PONT' => 39600,
 464          'PST' => -28800,
 465          'PWT' => 32400,
 466          'PYST' => -10800,
 467          'PYT' => -14400,
 468          'RET' => 14400,
 469          'ROTT' => -10800,
 470          'SAMST' => 18000,
 471          'SAMT' => 14400,
 472          'SAST' => 7200,
 473          'SBT' => 39600,
 474          'SCDT' => 46800,
 475          'SCST' => 43200,
 476          'SCT' => 14400,
 477          'SEST' => 3600,
 478          'SGT' => 28800,
 479          'SIT' => 28800,
 480          'SRT' => -10800,
 481          'SST' => -39600,
 482          'SYST' => 10800,
 483          'SYT' => 7200,
 484          'TFT' => 18000,
 485          'THAT' => -36000,
 486          'TJT' => 18000,
 487          'TKT' => -36000,
 488          'TMT' => 18000,
 489          'TOT' => 46800,
 490          'TPT' => 32400,
 491          'TRUT' => 36000,
 492          'TVT' => 43200,
 493          'TWT' => 28800,
 494          'UYST' => -7200,
 495          'UYT' => -10800,
 496          'UZT' => 18000,
 497          'VET' => -14400,
 498          'VLAST' => 39600,
 499          'VLAT' => 36000,
 500          'VOST' => 21600,
 501          'VUT' => 39600,
 502          'WAST' => 7200,
 503          'WAT' => 3600,
 504          'WDT' => 32400,
 505          'WEST' => 3600,
 506          'WFT' => 43200,
 507          'WIB' => 25200,
 508          'WIT' => 32400,
 509          'WITA' => 28800,
 510          'WKST' => 18000,
 511          'WST' => 28800,
 512          'YAKST' => 36000,
 513          'YAKT' => 32400,
 514          'YAPT' => 36000,
 515          'YEKST' => 21600,
 516          'YEKT' => 18000,
 517      ];
 518  
 519      /**
 520       * Cached PCRE for Date::$day
 521       *
 522       * @access protected
 523       * @var string
 524       */
 525      public $day_pcre;
 526  
 527      /**
 528       * Cached PCRE for Date::$month
 529       *
 530       * @access protected
 531       * @var string
 532       */
 533      public $month_pcre;
 534  
 535      /**
 536       * Array of user-added callback methods
 537       *
 538       * @access private
 539       * @var array<string>
 540       */
 541      public $built_in = [];
 542  
 543      /**
 544       * Array of user-added callback methods
 545       *
 546       * @access private
 547       * @var array<callable(string): (int|false)>
 548       */
 549      public $user = [];
 550  
 551      /**
 552       * Create new Date object, and set self::day_pcre,
 553       * self::month_pcre, and self::built_in
 554       *
 555       * @access private
 556       */
 557      public function __construct()
 558      {
 559          $this->day_pcre = '(' . implode('|', array_keys($this->day)) . ')';
 560          $this->month_pcre = '(' . implode('|', array_keys($this->month)) . ')';
 561  
 562          static $cache;
 563          if (!isset($cache[get_class($this)])) {
 564              $all_methods = get_class_methods($this);
 565  
 566              foreach ($all_methods as $method) {
 567                  if (strtolower(substr($method, 0, 5)) === 'date_') {
 568                      $cache[get_class($this)][] = $method;
 569                  }
 570              }
 571          }
 572  
 573          foreach ($cache[get_class($this)] as $method) {
 574              $this->built_in[] = $method;
 575          }
 576      }
 577  
 578      /**
 579       * Get the object
 580       *
 581       * @access public
 582       * @return Date
 583       */
 584      public static function get()
 585      {
 586          static $object;
 587          if (!$object) {
 588              $object = new Date();
 589          }
 590          return $object;
 591      }
 592  
 593      /**
 594       * Parse a date
 595       *
 596       * @final
 597       * @access public
 598       * @param string $date Date to parse
 599       * @return int|false Timestamp corresponding to date string, or false on failure
 600       */
 601      public function parse(string $date)
 602      {
 603          foreach ($this->user as $method) {
 604              if (($returned = call_user_func($method, $date)) !== false) {
 605                  return (int) $returned;
 606              }
 607          }
 608  
 609          foreach ($this->built_in as $method) {
 610              // TODO: we should really check this in constructor but that would require private properties.
 611              /** @var callable(string): (int|false) */
 612              $callable = [$this, $method];
 613              if (($returned = call_user_func($callable, $date)) !== false) {
 614                  return $returned;
 615              }
 616          }
 617  
 618          return false;
 619      }
 620  
 621      /**
 622       * Add a callback method to parse a date
 623       *
 624       * @final
 625       * @access public
 626       * @param callable $callback
 627       * @return void
 628       */
 629      public function add_callback(callable $callback)
 630      {
 631          $this->user[] = $callback;
 632      }
 633  
 634      /**
 635       * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
 636       * well as allowing any of upper or lower case "T", horizontal tabs, or
 637       * spaces to be used as the time separator (including more than one))
 638       *
 639       * @access protected
 640       * @param string $date
 641       * @return int|false Timestamp
 642       */
 643      public function date_w3cdtf(string $date)
 644      {
 645          $pcre = <<<'PCRE'
 646              /
 647              ^
 648              (?P<year>[0-9]{4})
 649              (?:
 650                  -?
 651                  (?P<month>[0-9]{2})
 652                  (?:
 653                      -?
 654                      (?P<day>[0-9]{2})
 655                      (?:
 656                          [Tt\x09\x20]+
 657                          (?P<hour>[0-9]{2})
 658                          (?:
 659                              :?
 660                              (?P<minute>[0-9]{2})
 661                              (?:
 662                                  :?
 663                                  (?P<second>[0-9]{2})
 664                                  (?:
 665                                      .
 666                                      (?P<second_fraction>[0-9]*)
 667                                  )?
 668                              )?
 669                          )?
 670                          (?:
 671                              (?P<zulu>Z)
 672                              |   (?P<tz_sign>[+\-])
 673                                  (?P<tz_hour>[0-9]{1,2})
 674                                  :?
 675                                  (?P<tz_minute>[0-9]{1,2})
 676                          )
 677                      )?
 678                  )?
 679              )?
 680              $
 681              /x
 682  PCRE;
 683          if (preg_match($pcre, $date, $match)) {
 684              // Fill in empty matches and convert to proper types.
 685              $year = (int) $match['year'];
 686              $month = isset($match['month']) ? (int) $match['month'] : 1;
 687              $day = isset($match['day']) ? (int) $match['day'] : 1;
 688              $hour = isset($match['hour']) ? (int) $match['hour'] : 0;
 689              $minute = isset($match['minute']) ? (int) $match['minute'] : 0;
 690              $second = isset($match['second']) ? (int) $match['second'] : 0;
 691              $second_fraction = isset($match['second_fraction']) ? ((int) $match['second_fraction']) / (10 ** strlen($match['second_fraction'])) : 0;
 692              $tz_sign = ($match['tz_sign'] ?? '') === '-' ? -1 : 1;
 693              $tz_hour = isset($match['tz_hour']) ? (int) $match['tz_hour'] : 0;
 694              $tz_minute = isset($match['tz_minute']) ? (int) $match['tz_minute'] : 0;
 695  
 696              // Numeric timezone
 697              $timezone = $tz_hour * 3600;
 698              $timezone += $tz_minute * 60;
 699              $timezone *= $tz_sign;
 700  
 701              // Convert the number of seconds to an integer, taking decimals into account
 702              $second = (int) round($second + $second_fraction);
 703  
 704              return gmmktime($hour, $minute, $second, $month, $day, $year) - $timezone;
 705          }
 706  
 707          return false;
 708      }
 709  
 710      /**
 711       * Remove RFC822 comments
 712       *
 713       * @access protected
 714       * @param string $string Data to strip comments from
 715       * @return string Comment stripped string
 716       */
 717      public function remove_rfc2822_comments(string $string)
 718      {
 719          $position = 0;
 720          $length = strlen($string);
 721          $depth = 0;
 722  
 723          $output = '';
 724  
 725          while ($position < $length && ($pos = strpos($string, '(', $position)) !== false) {
 726              $output .= substr($string, $position, $pos - $position);
 727              $position = $pos + 1;
 728              if ($pos === 0 || $string[$pos - 1] !== '\\') {
 729                  $depth++;
 730                  while ($depth && $position < $length) {
 731                      $position += strcspn($string, '()', $position);
 732                      if ($string[$position - 1] === '\\') {
 733                          $position++;
 734                          continue;
 735                      } elseif (isset($string[$position])) {
 736                          switch ($string[$position]) {
 737                              case '(':
 738                                  $depth++;
 739                                  break;
 740  
 741                              case ')':
 742                                  $depth--;
 743                                  break;
 744                          }
 745                          $position++;
 746                      } else {
 747                          break;
 748                      }
 749                  }
 750              } else {
 751                  $output .= '(';
 752              }
 753          }
 754          $output .= substr($string, $position);
 755  
 756          return $output;
 757      }
 758  
 759      /**
 760       * Parse RFC2822's date format
 761       *
 762       * @access protected
 763       * @param string $date
 764       * @return int|false Timestamp
 765       */
 766      public function date_rfc2822(string $date)
 767      {
 768          static $pcre;
 769          if (!$pcre) {
 770              $wsp = '[\x09\x20]';
 771              $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
 772              $optional_fws = $fws . '?';
 773              $day_name = $this->day_pcre;
 774              $month = $this->month_pcre;
 775              $day = '([0-9]{1,2})';
 776              $hour = $minute = $second = '([0-9]{2})';
 777              $year = '([0-9]{2,4})';
 778              $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
 779              $character_zone = '([A-Z]{1,5})';
 780              $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
 781              $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
 782          }
 783          if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match)) {
 784              /*
 785              Capturing subpatterns:
 786              1: Day name
 787              2: Day
 788              3: Month
 789              4: Year
 790              5: Hour
 791              6: Minute
 792              7: Second
 793              8: Timezone ±
 794              9: Timezone hours
 795              10: Timezone minutes
 796              11: Alphabetic timezone
 797              */
 798  
 799              $day = (int) $match[2];
 800              // Find the month number
 801              $month = $this->month[strtolower($match[3])];
 802              $year = (int) $match[4];
 803              $hour = (int) $match[5];
 804              $minute = (int) $match[6];
 805              // Second is optional, if it is empty set it to zero
 806              $second = (int) $match[7];
 807  
 808              $tz_sign = $match[8];
 809              $tz_hour = (int) $match[9];
 810              $tz_minute = (int) $match[10];
 811              $tz_code = isset($match[11]) ? strtoupper($match[11]) : '';
 812  
 813              // Numeric timezone
 814              if ($tz_sign !== '') {
 815                  $timezone = $tz_hour * 3600;
 816                  $timezone += $tz_minute * 60;
 817                  if ($tz_sign === '-') {
 818                      $timezone = 0 - $timezone;
 819                  }
 820              }
 821              // Character timezone
 822              elseif (isset($this->timezone[$tz_code])) {
 823                  $timezone = $this->timezone[$tz_code];
 824              }
 825              // Assume everything else to be -0000
 826              else {
 827                  $timezone = 0;
 828              }
 829  
 830              // Deal with 2/3 digit years
 831              if ($year < 50) {
 832                  $year += 2000;
 833              } elseif ($year < 1000) {
 834                  $year += 1900;
 835              }
 836  
 837              return gmmktime($hour, $minute, $second, $month, $day, $year) - $timezone;
 838          }
 839  
 840          return false;
 841      }
 842  
 843      /**
 844       * Parse RFC850's date format
 845       *
 846       * @access protected
 847       * @param string $date
 848       * @return int|false Timestamp
 849       */
 850      public function date_rfc850(string $date)
 851      {
 852          static $pcre;
 853          if (!$pcre) {
 854              $space = '[\x09\x20]+';
 855              $day_name = $this->day_pcre;
 856              $month = $this->month_pcre;
 857              $day = '([0-9]{1,2})';
 858              $year = $hour = $minute = $second = '([0-9]{2})';
 859              $zone = '([A-Z]{1,5})';
 860              $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
 861          }
 862          if (preg_match($pcre, $date, $match)) {
 863              /*
 864              Capturing subpatterns:
 865              1: Day name
 866              2: Day
 867              3: Month
 868              4: Year
 869              5: Hour
 870              6: Minute
 871              7: Second
 872              8: Timezone
 873              */
 874  
 875              $day = (int) $match[2];
 876              // Month
 877              $month = $this->month[strtolower($match[3])];
 878              $year = (int) $match[4];
 879              $hour = (int) $match[5];
 880              $minute = (int) $match[6];
 881              // Second is optional, if it is empty set it to zero
 882              $second = (int) $match[7];
 883  
 884              $tz_code = strtoupper($match[8]);
 885  
 886              // Character timezone
 887              if (isset($this->timezone[$tz_code])) {
 888                  $timezone = $this->timezone[$tz_code];
 889              }
 890              // Assume everything else to be -0000
 891              else {
 892                  $timezone = 0;
 893              }
 894  
 895              // Deal with 2 digit year
 896              if ($year < 50) {
 897                  $year += 2000;
 898              } else {
 899                  $year += 1900;
 900              }
 901  
 902              return gmmktime($hour, $minute, $second, $month, $day, $year) - $timezone;
 903          }
 904  
 905          return false;
 906      }
 907  
 908      /**
 909       * Parse C99's asctime()'s date format
 910       *
 911       * @access protected
 912       * @param string $date
 913       * @return int|false Timestamp
 914       */
 915      public function date_asctime(string $date)
 916      {
 917          static $pcre;
 918          if (!$pcre) {
 919              $space = '[\x09\x20]+';
 920              $wday_name = $this->day_pcre;
 921              $mon_name = $this->month_pcre;
 922              $day = '([0-9]{1,2})';
 923              $hour = $sec = $min = '([0-9]{2})';
 924              $year = '([0-9]{4})';
 925              $terminator = '\x0A?\x00?';
 926              $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
 927          }
 928          if (preg_match($pcre, $date, $match)) {
 929              /*
 930              Capturing subpatterns:
 931              1: Day name
 932              2: Month
 933              3: Day
 934              4: Hour
 935              5: Minute
 936              6: Second
 937              7: Year
 938              */
 939  
 940              $month = $this->month[strtolower($match[2])];
 941              return gmmktime((int) $match[4], (int) $match[5], (int) $match[6], $month, (int) $match[3], (int) $match[7]);
 942          }
 943  
 944          return false;
 945      }
 946  
 947      /**
 948       * Parse dates using strtotime()
 949       *
 950       * @access protected
 951       * @param string $date
 952       * @return int|false Timestamp
 953       */
 954      public function date_strtotime(string $date)
 955      {
 956          $strtotime = strtotime($date);
 957          if ($strtotime === -1 || $strtotime === false) {
 958              return false;
 959          }
 960  
 961          return $strtotime;
 962      }
 963  }
 964  
 965  class_alias('SimplePie\Parse\Date', 'SimplePie_Parse_Date');


Generated : Fri Oct 10 08:20:03 2025 Cross-referenced by PHPXref