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