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