wp/wp-includes/SimplePie/src/Parse/Date.php
changeset 22 8c2e4d02f4ef
equal deleted inserted replaced
21:48c4eec2b7e6 22:8c2e4d02f4ef
       
     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');