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