Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

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