web/wp-includes/SimplePie/Parse/Date.php
changeset 204 09a1c134465b
equal deleted inserted replaced
203:f507feede89a 204:09a1c134465b
       
     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