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