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