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


Generated : Thu Oct 24 08:20:01 2024 Cross-referenced by PHPXref