~canonical-sysadmins/wordpress/4.7.4

« back to all changes in this revision

Viewing changes to wp-includes/SimplePie/Parse/Date.php

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-2012, 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.1
 
37
 * @copyright 2004-2012 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
 */
 
44
 
 
45
 
 
46
/**
 
47
 * Date Parser
 
48
 *
 
49
 * @package SimplePie
 
50
 * @subpackage Parsing
 
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