home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress2 / wp-includes / SimplePie / Parse / Date.php
Encoding:
PHP Script  |  2015-10-19  |  19.2 KB  |  985 lines

  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.         'CEST' => 7200,
  335.         'CET' => 3600,
  336.         'CGST' => -7200,
  337.         'CGT' => -10800,
  338.         'CHADT' => 49500,
  339.         'CHAST' => 45900,
  340.         'CIST' => -28800,
  341.         'CKT' => -36000,
  342.         'CLDT' => -10800,
  343.         'CLST' => -14400,
  344.         'COT' => -18000,
  345.         'CST' => -21600,
  346.         'CVT' => -3600,
  347.         'CXT' => 25200,
  348.         'DAVT' => 25200,
  349.         'DTAT' => 36000,
  350.         'EADT' => -18000,
  351.         'EAST' => -21600,
  352.         'EAT' => 10800,
  353.         'ECT' => -18000,
  354.         'EDT' => -14400,
  355.         'EEST' => 10800,
  356.         'EET' => 7200,
  357.         'EGT' => -3600,
  358.         'EKST' => 21600,
  359.         'EST' => -18000,
  360.         'FJT' => 43200,
  361.         'FKDT' => -10800,
  362.         'FKST' => -14400,
  363.         'FNT' => -7200,
  364.         'GALT' => -21600,
  365.         'GEDT' => 14400,
  366.         'GEST' => 10800,
  367.         'GFT' => -10800,
  368.         'GILT' => 43200,
  369.         'GIT' => -32400,
  370.         'GST' => 14400,
  371.         'GST' => -7200,
  372.         'GYT' => -14400,
  373.         'HAA' => -10800,
  374.         'HAC' => -18000,
  375.         'HADT' => -32400,
  376.         'HAE' => -14400,
  377.         'HAP' => -25200,
  378.         'HAR' => -21600,
  379.         'HAST' => -36000,
  380.         'HAT' => -9000,
  381.         'HAY' => -28800,
  382.         'HKST' => 28800,
  383.         'HMT' => 18000,
  384.         'HNA' => -14400,
  385.         'HNC' => -21600,
  386.         'HNE' => -18000,
  387.         'HNP' => -28800,
  388.         'HNR' => -25200,
  389.         'HNT' => -12600,
  390.         'HNY' => -32400,
  391.         'IRDT' => 16200,
  392.         'IRKST' => 32400,
  393.         'IRKT' => 28800,
  394.         'IRST' => 12600,
  395.         'JFDT' => -10800,
  396.         'JFST' => -14400,
  397.         'JST' => 32400,
  398.         'KGST' => 21600,
  399.         'KGT' => 18000,
  400.         'KOST' => 39600,
  401.         'KOVST' => 28800,
  402.         'KOVT' => 25200,
  403.         'KRAST' => 28800,
  404.         'KRAT' => 25200,
  405.         'KST' => 32400,
  406.         'LHDT' => 39600,
  407.         'LHST' => 37800,
  408.         'LINT' => 50400,
  409.         'LKT' => 21600,
  410.         'MAGST' => 43200,
  411.         'MAGT' => 39600,
  412.         'MAWT' => 21600,
  413.         'MDT' => -21600,
  414.         'MESZ' => 7200,
  415.         'MEZ' => 3600,
  416.         'MHT' => 43200,
  417.         'MIT' => -34200,
  418.         'MNST' => 32400,
  419.         'MSDT' => 14400,
  420.         'MSST' => 10800,
  421.         'MST' => -25200,
  422.         'MUT' => 14400,
  423.         'MVT' => 18000,
  424.         'MYT' => 28800,
  425.         'NCT' => 39600,
  426.         'NDT' => -9000,
  427.         'NFT' => 41400,
  428.         'NMIT' => 36000,
  429.         'NOVST' => 25200,
  430.         'NOVT' => 21600,
  431.         'NPT' => 20700,
  432.         'NRT' => 43200,
  433.         'NST' => -12600,
  434.         'NUT' => -39600,
  435.         'NZDT' => 46800,
  436.         'NZST' => 43200,
  437.         'OMSST' => 25200,
  438.         'OMST' => 21600,
  439.         'PDT' => -25200,
  440.         'PET' => -18000,
  441.         'PETST' => 46800,
  442.         'PETT' => 43200,
  443.         'PGT' => 36000,
  444.         'PHOT' => 46800,
  445.         'PHT' => 28800,
  446.         'PKT' => 18000,
  447.         'PMDT' => -7200,
  448.         'PMST' => -10800,
  449.         'PONT' => 39600,
  450.         'PST' => -28800,
  451.         'PWT' => 32400,
  452.         'PYST' => -10800,
  453.         'PYT' => -14400,
  454.         'RET' => 14400,
  455.         'ROTT' => -10800,
  456.         'SAMST' => 18000,
  457.         'SAMT' => 14400,
  458.         'SAST' => 7200,
  459.         'SBT' => 39600,
  460.         'SCDT' => 46800,
  461.         'SCST' => 43200,
  462.         'SCT' => 14400,
  463.         'SEST' => 3600,
  464.         'SGT' => 28800,
  465.         'SIT' => 28800,
  466.         'SRT' => -10800,
  467.         'SST' => -39600,
  468.         'SYST' => 10800,
  469.         'SYT' => 7200,
  470.         'TFT' => 18000,
  471.         'THAT' => -36000,
  472.         'TJT' => 18000,
  473.         'TKT' => -36000,
  474.         'TMT' => 18000,
  475.         'TOT' => 46800,
  476.         'TPT' => 32400,
  477.         'TRUT' => 36000,
  478.         'TVT' => 43200,
  479.         'TWT' => 28800,
  480.         'UYST' => -7200,
  481.         'UYT' => -10800,
  482.         'UZT' => 18000,
  483.         'VET' => -14400,
  484.         'VLAST' => 39600,
  485.         'VLAT' => 36000,
  486.         'VOST' => 21600,
  487.         'VUT' => 39600,
  488.         'WAST' => 7200,
  489.         'WAT' => 3600,
  490.         'WDT' => 32400,
  491.         'WEST' => 3600,
  492.         'WFT' => 43200,
  493.         'WIB' => 25200,
  494.         'WIT' => 32400,
  495.         'WITA' => 28800,
  496.         'WKST' => 18000,
  497.         'WST' => 28800,
  498.         'YAKST' => 36000,
  499.         'YAKT' => 32400,
  500.         'YAPT' => 36000,
  501.         'YEKST' => 21600,
  502.         'YEKT' => 18000,
  503.     );
  504.  
  505.     /**
  506.      * Cached PCRE for SimplePie_Parse_Date::$day
  507.      *
  508.      * @access protected
  509.      * @var string
  510.      */
  511.     var $day_pcre;
  512.  
  513.     /**
  514.      * Cached PCRE for SimplePie_Parse_Date::$month
  515.      *
  516.      * @access protected
  517.      * @var string
  518.      */
  519.     var $month_pcre;
  520.  
  521.     /**
  522.      * Array of user-added callback methods
  523.      *
  524.      * @access private
  525.      * @var array
  526.      */
  527.     var $built_in = array();
  528.  
  529.     /**
  530.      * Array of user-added callback methods
  531.      *
  532.      * @access private
  533.      * @var array
  534.      */
  535.     var $user = array();
  536.  
  537.     /**
  538.      * Create new SimplePie_Parse_Date object, and set self::day_pcre,
  539.      * self::month_pcre, and self::built_in
  540.      *
  541.      * @access private
  542.      */
  543.     public function __construct()
  544.     {
  545.         $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
  546.         $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
  547.  
  548.         static $cache;
  549.         if (!isset($cache[get_class($this)]))
  550.         {
  551.             $all_methods = get_class_methods($this);
  552.  
  553.             foreach ($all_methods as $method)
  554.             {
  555.                 if (strtolower(substr($method, 0, 5)) === 'date_')
  556.                 {
  557.                     $cache[get_class($this)][] = $method;
  558.                 }
  559.             }
  560.         }
  561.  
  562.         foreach ($cache[get_class($this)] as $method)
  563.         {
  564.             $this->built_in[] = $method;
  565.         }
  566.     }
  567.  
  568.     /**
  569.      * Get the object
  570.      *
  571.      * @access public
  572.      */
  573.     public static function get()
  574.     {
  575.         static $object;
  576.         if (!$object)
  577.         {
  578.             $object = new SimplePie_Parse_Date;
  579.         }
  580.         return $object;
  581.     }
  582.  
  583.     /**
  584.      * Parse a date
  585.      *
  586.      * @final
  587.      * @access public
  588.      * @param string $date Date to parse
  589.      * @return int Timestamp corresponding to date string, or false on failure
  590.      */
  591.     public function parse($date)
  592.     {
  593.         foreach ($this->user as $method)
  594.         {
  595.             if (($returned = call_user_func($method, $date)) !== false)
  596.             {
  597.                 return $returned;
  598.             }
  599.         }
  600.  
  601.         foreach ($this->built_in as $method)
  602.         {
  603.             if (($returned = call_user_func(array($this, $method), $date)) !== false)
  604.             {
  605.                 return $returned;
  606.             }
  607.         }
  608.  
  609.         return false;
  610.     }
  611.  
  612.     /**
  613.      * Add a callback method to parse a date
  614.      *
  615.      * @final
  616.      * @access public
  617.      * @param callable $callback
  618.      */
  619.     public function add_callback($callback)
  620.     {
  621.         if (is_callable($callback))
  622.         {
  623.             $this->user[] = $callback;
  624.         }
  625.         else
  626.         {
  627.             trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
  628.         }
  629.     }
  630.  
  631.     /**
  632.      * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
  633.      * well as allowing any of upper or lower case "T", horizontal tabs, or
  634.      * spaces to be used as the time seperator (including more than one))
  635.      *
  636.      * @access protected
  637.      * @return int Timestamp
  638.      */
  639.     public function date_w3cdtf($date)
  640.     {
  641.         static $pcre;
  642.         if (!$pcre)
  643.         {
  644.             $year = '([0-9]{4})';
  645.             $month = $day = $hour = $minute = $second = '([0-9]{2})';
  646.             $decimal = '([0-9]*)';
  647.             $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
  648.             $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
  649.         }
  650.         if (preg_match($pcre, $date, $match))
  651.         {
  652.             /*
  653.             Capturing subpatterns:
  654.             1: Year
  655.             2: Month
  656.             3: Day
  657.             4: Hour
  658.             5: Minute
  659.             6: Second
  660.             7: Decimal fraction of a second
  661.             8: Zulu
  662.             9: Timezone ┬▒
  663.             10: Timezone hours
  664.             11: Timezone minutes
  665.             */
  666.  
  667.             // Fill in empty matches
  668.             for ($i = count($match); $i <= 3; $i++)
  669.             {
  670.                 $match[$i] = '1';
  671.             }
  672.  
  673.             for ($i = count($match); $i <= 7; $i++)
  674.             {
  675.                 $match[$i] = '0';
  676.             }
  677.  
  678.             // Numeric timezone
  679.             if (isset($match[9]) && $match[9] !== '')
  680.             {
  681.                 $timezone = $match[10] * 3600;
  682.                 $timezone += $match[11] * 60;
  683.                 if ($match[9] === '-')
  684.                 {
  685.                     $timezone = 0 - $timezone;
  686.                 }
  687.             }
  688.             else
  689.             {
  690.                 $timezone = 0;
  691.             }
  692.  
  693.             // Convert the number of seconds to an integer, taking decimals into account
  694.             $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
  695.  
  696.             return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
  697.         }
  698.         else
  699.         {
  700.             return false;
  701.         }
  702.     }
  703.  
  704.     /**
  705.      * Remove RFC822 comments
  706.      *
  707.      * @access protected
  708.      * @param string $data Data to strip comments from
  709.      * @return string Comment stripped string
  710.      */
  711.     public function remove_rfc2822_comments($string)
  712.     {
  713.         $string = (string) $string;
  714.         $position = 0;
  715.         $length = strlen($string);
  716.         $depth = 0;
  717.  
  718.         $output = '';
  719.  
  720.         while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
  721.         {
  722.             $output .= substr($string, $position, $pos - $position);
  723.             $position = $pos + 1;
  724.             if ($string[$pos - 1] !== '\\')
  725.             {
  726.                 $depth++;
  727.                 while ($depth && $position < $length)
  728.                 {
  729.                     $position += strcspn($string, '()', $position);
  730.                     if ($string[$position - 1] === '\\')
  731.                     {
  732.                         $position++;
  733.                         continue;
  734.                     }
  735.                     elseif (isset($string[$position]))
  736.                     {
  737.                         switch ($string[$position])
  738.                         {
  739.                             case '(':
  740.                                 $depth++;
  741.                                 break;
  742.  
  743.                             case ')':
  744.                                 $depth--;
  745.                                 break;
  746.                         }
  747.                         $position++;
  748.                     }
  749.                     else
  750.                     {
  751.                         break;
  752.                     }
  753.                 }
  754.             }
  755.             else
  756.             {
  757.                 $output .= '(';
  758.             }
  759.         }
  760.         $output .= substr($string, $position);
  761.  
  762.         return $output;
  763.     }
  764.  
  765.     /**
  766.      * Parse RFC2822's date format
  767.      *
  768.      * @access protected
  769.      * @return int Timestamp
  770.      */
  771.     public function date_rfc2822($date)
  772.     {
  773.         static $pcre;
  774.         if (!$pcre)
  775.         {
  776.             $wsp = '[\x09\x20]';
  777.             $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
  778.             $optional_fws = $fws . '?';
  779.             $day_name = $this->day_pcre;
  780.             $month = $this->month_pcre;
  781.             $day = '([0-9]{1,2})';
  782.             $hour = $minute = $second = '([0-9]{2})';
  783.             $year = '([0-9]{2,4})';
  784.             $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
  785.             $character_zone = '([A-Z]{1,5})';
  786.             $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
  787.             $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';
  788.         }
  789.         if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
  790.         {
  791.             /*
  792.             Capturing subpatterns:
  793.             1: Day name
  794.             2: Day
  795.             3: Month
  796.             4: Year
  797.             5: Hour
  798.             6: Minute
  799.             7: Second
  800.             8: Timezone ┬▒
  801.             9: Timezone hours
  802.             10: Timezone minutes
  803.             11: Alphabetic timezone
  804.             */
  805.  
  806.             // Find the month number
  807.             $month = $this->month[strtolower($match[3])];
  808.  
  809.             // Numeric timezone
  810.             if ($match[8] !== '')
  811.             {
  812.                 $timezone = $match[9] * 3600;
  813.                 $timezone += $match[10] * 60;
  814.                 if ($match[8] === '-')
  815.                 {
  816.                     $timezone = 0 - $timezone;
  817.                 }
  818.             }
  819.             // Character timezone
  820.             elseif (isset($this->timezone[strtoupper($match[11])]))
  821.             {
  822.                 $timezone = $this->timezone[strtoupper($match[11])];
  823.             }
  824.             // Assume everything else to be -0000
  825.             else
  826.             {
  827.                 $timezone = 0;
  828.             }
  829.  
  830.             // Deal with 2/3 digit years
  831.             if ($match[4] < 50)
  832.             {
  833.                 $match[4] += 2000;
  834.             }
  835.             elseif ($match[4] < 1000)
  836.             {
  837.                 $match[4] += 1900;
  838.             }
  839.  
  840.             // Second is optional, if it is empty set it to zero
  841.             if ($match[7] !== '')
  842.             {
  843.                 $second = $match[7];
  844.             }
  845.             else
  846.             {
  847.                 $second = 0;
  848.             }
  849.  
  850.             return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
  851.         }
  852.         else
  853.         {
  854.             return false;
  855.         }
  856.     }
  857.  
  858.     /**
  859.      * Parse RFC850's date format
  860.      *
  861.      * @access protected
  862.      * @return int Timestamp
  863.      */
  864.     public function date_rfc850($date)
  865.     {
  866.         static $pcre;
  867.         if (!$pcre)
  868.         {
  869.             $space = '[\x09\x20]+';
  870.             $day_name = $this->day_pcre;
  871.             $month = $this->month_pcre;
  872.             $day = '([0-9]{1,2})';
  873.             $year = $hour = $minute = $second = '([0-9]{2})';
  874.             $zone = '([A-Z]{1,5})';
  875.             $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
  876.         }
  877.         if (preg_match($pcre, $date, $match))
  878.         {
  879.             /*
  880.             Capturing subpatterns:
  881.             1: Day name
  882.             2: Day
  883.             3: Month
  884.             4: Year
  885.             5: Hour
  886.             6: Minute
  887.             7: Second
  888.             8: Timezone
  889.             */
  890.  
  891.             // Month
  892.             $month = $this->month[strtolower($match[3])];
  893.  
  894.             // Character timezone
  895.             if (isset($this->timezone[strtoupper($match[8])]))
  896.             {
  897.                 $timezone = $this->timezone[strtoupper($match[8])];
  898.             }
  899.             // Assume everything else to be -0000
  900.             else
  901.             {
  902.                 $timezone = 0;
  903.             }
  904.  
  905.             // Deal with 2 digit year
  906.             if ($match[4] < 50)
  907.             {
  908.                 $match[4] += 2000;
  909.             }
  910.             else
  911.             {
  912.                 $match[4] += 1900;
  913.             }
  914.  
  915.             return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
  916.         }
  917.         else
  918.         {
  919.             return false;
  920.         }
  921.     }
  922.  
  923.     /**
  924.      * Parse C99's asctime()'s date format
  925.      *
  926.      * @access protected
  927.      * @return int Timestamp
  928.      */
  929.     public function date_asctime($date)
  930.     {
  931.         static $pcre;
  932.         if (!$pcre)
  933.         {
  934.             $space = '[\x09\x20]+';
  935.             $wday_name = $this->day_pcre;
  936.             $mon_name = $this->month_pcre;
  937.             $day = '([0-9]{1,2})';
  938.             $hour = $sec = $min = '([0-9]{2})';
  939.             $year = '([0-9]{4})';
  940.             $terminator = '\x0A?\x00?';
  941.             $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
  942.         }
  943.         if (preg_match($pcre, $date, $match))
  944.         {
  945.             /*
  946.             Capturing subpatterns:
  947.             1: Day name
  948.             2: Month
  949.             3: Day
  950.             4: Hour
  951.             5: Minute
  952.             6: Second
  953.             7: Year
  954.             */
  955.  
  956.             $month = $this->month[strtolower($match[2])];
  957.             return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
  958.         }
  959.         else
  960.         {
  961.             return false;
  962.         }
  963.     }
  964.  
  965.     /**
  966.      * Parse dates using strtotime()
  967.      *
  968.      * @access protected
  969.      * @return int Timestamp
  970.      */
  971.     public function date_strtotime($date)
  972.     {
  973.         $strtotime = strtotime($date);
  974.         if ($strtotime === -1 || $strtotime === false)
  975.         {
  976.             return false;
  977.         }
  978.         else
  979.         {
  980.             return $strtotime;
  981.         }
  982.     }
  983. }
  984.  
  985.