Source for file jDateTime.class.php

Documentation is available at jDateTime.class.php

  1. <?php
  2. /**
  3. @package     jelix
  4. @subpackage  utils
  5. @author      GĂ©rald Croes, Laurent Jouanneau
  6. @contributor Laurent Jouanneau, Julien Issler
  7. @contributor Loic Mathaud
  8. @contributor Florian Hatat
  9. @contributor Hadrien Lanneau <hadrien@over-blog.com>
  10. @copyright   2005-2008 Laurent Jouanneau
  11. @copyright   2007 Loic Mathaud
  12. @copyright   2007-2008 Florian Hatat
  13. @copyright   2001-2005 CopixTeam, GeraldCroes, Laurent Jouanneau
  14. @copyright   2008 Julien Issler
  15. @copyright   2010 Hadrien Lanneau
  16. *
  17. *  This class was get originally from the Copix project (CopixDate.lib.php, Copix 2.3dev20050901, http://www.copix.org)
  18. *  Only few lines of code are still copyrighted 2001-2005 CopixTeam (LGPL licence).
  19. *  Initial authors of this Copix classes are Gerald Croes and Laurent Jouanneau,
  20. *  and this class was adapted/improved for Jelix by Laurent Jouanneau
  21. *
  22. @link        http://www.jelix.org
  23. @licence     http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public Licence, see LICENCE file
  24. */
  25.  
  26. #if PHP50
  27. if(!function_exists('strptime'))// existe depuis php 5.1
  28.     /**
  29.      * @ignore
  30.      */
  31.     function strptime $strdate$format ){
  32.         // It's not a full compatibility with strptime of PHP5.1, but it is
  33.         // enough for our needs
  34.         $plop array'S'=>'tm_sec''M'=>'tm_min''H'=>'tm_hour',
  35.             'd'=>'tm_mday''m'=>'tm_mon''Y'=>'tm_year');
  36.  
  37.         $regexp preg_quote($format'/');
  38.         $regexp str_replace(
  39.                 array('%d','%m','%Y','%H','%M','%S'),
  40.                 array('(?P<tm_mday>\d{2})','(?P<tm_mon>\d{2})',
  41.                       '(?P<tm_year>\d{4})','(?P<tm_hour>\d{2})',
  42.                       '(?P<tm_min>\d{2})','(?P<tm_sec>\d{2})'),
  43.                 $regexp);
  44.         if(preg_match('/^'.$regexp.'$/'$strdate$m)){
  45.             $result=array('tm_sec'=>0,'tm_min'=>0,'tm_hour'=>0,'tm_mday'=>0,'tm_mon'=>0,'tm_year'=>0,'tm_wday'=>0,'tm_yday'=>0,'unparsed'=>'');
  46.             foreach($m as $key => $value){
  47.                 if(!isset($result[$key])){
  48.                     continue;
  49.                 }
  50.                 $result[$keyintval($value);
  51.                 switch($key){
  52.                 case 'tm_mon':
  53.                     $result[$key]--;
  54.                     break;
  55.                 case 'tm_year':
  56.                     $result[$key-= 1900;
  57.                     break;
  58.                 default:
  59.                     break;
  60.                 }
  61.             }
  62.             return $result;
  63.         }
  64.         return false;
  65.     }
  66. }
  67. #endif
  68.  
  69. /**
  70.  * Utility to manipulate dates and convert date format
  71.  * @package     jelix
  72.  * @subpackage  utils
  73.  */
  74. class jDateTime {
  75.     public $day;
  76.     public $month;
  77.     public $year;
  78.     public $hour;
  79.     public $minute;
  80.     public $second;
  81.  
  82.     public $defaultFormat = 11;
  83.  
  84.     const LANG_DFORMAT=10;
  85.     const LANG_DTFORMAT=11;
  86.     const LANG_TFORMAT=12;
  87.     const DB_DFORMAT=20;
  88.     const DB_DTFORMAT=21;
  89.     const DB_TFORMAT=22;
  90.     const ISO8601_FORMAT=40;
  91.     const TIMESTAMP_FORMAT=50;
  92.     const RFC822_FORMAT=60;
  93.     const RFC2822_FORMAT=61;
  94.  
  95.     /**#@+
  96.      * use DB_* consts instead
  97.      * @deprecated
  98.      */
  99.     const BD_DFORMAT=20;
  100.     const BD_DTFORMAT=21;
  101.     const BD_TFORMAT=22;
  102.     /**#@-*/
  103.  
  104.     /**
  105.      *
  106.      */
  107.     function __construct($year=0$month=0$day=0$hour=0$minute=0$second=0){
  108.         $this->year = $year;
  109.         $this->month = $month;
  110.         $this->day = $day;
  111.         $this->hour = $hour;
  112.         $this->minute = $minute;
  113.         $this->second = $second;
  114.  
  115.         if(!$this->_check())
  116.         {
  117.           throw new jException('jelix~errors.datetime.invalid',
  118.               array($this->year$this->month$this->day,
  119.                 $this->hour$this->minute$this->second));
  120.         }
  121.     }
  122.  
  123.     /**
  124.      * checks if the current jDateTime object is a valid gregorian date/time
  125.      * @return bool true if the date/time are valid.
  126.      */
  127.     private function _check({
  128.         // Only check the date if it is defined (eg. day, month and year are
  129.         // strictly positive).
  130.         if($this->day > && $this->month > && $this->year > 0
  131.             && !checkdate($this->month$this->day$this->year))
  132.         {
  133.             return false;
  134.         }
  135.         if(!(($this->second >= 0&& ($this->second < 60)
  136.             && ($this->minute >= 0&& ($this->minute < 60)
  137.             && ($this->hour >= 0&& ($this->hour < 24)))
  138.         {
  139.             return false;
  140.         }
  141.         return true;
  142.     }
  143.  
  144.     /**
  145.      * convert the date to a string format
  146.      * @param int $format one of the class constant xxx_FORMAT, or -1 if it should use the default format
  147.      * @return string the string date
  148.      * @see jDateTime:$defaultFormat
  149.      */
  150.     function toString($format=-1){
  151.         if($format==-1)
  152.             $format $this->defaultFormat;
  153.  
  154.         $str='';
  155.         switch($format){
  156.            case self::LANG_DFORMAT:
  157.                $t mktime $this->hour$this->minute,$this->second $this->month$this->day$this->year );
  158.                $lf jLocale::get('jelix~format.date');
  159.                $str date($lf$t);
  160.                break;
  161.            case self::LANG_DTFORMAT:
  162.                $t mktime $this->hour$this->minute,$this->second $this->month$this->day$this->year );
  163.                $lf jLocale::get('jelix~format.datetime');
  164.                $str date($lf$t);
  165.                break;
  166.            case self::LANG_TFORMAT:
  167.                $t mktime $this->hour$this->minute,$this->second 0);
  168.                $lf jLocale::get('jelix~format.time');
  169.                $str date($lf$t);
  170.                break;
  171.            case self::DB_DFORMAT:
  172.            case self::BD_DFORMAT:
  173.                $str sprintf('%04d-%02d-%02d'$this->year$this->month$this->day);
  174.                break;
  175.            case self::DB_DTFORMAT:
  176.            case self::BD_DTFORMAT:
  177.                $str sprintf('%04d-%02d-%02d %02d:%02d:%02d'$this->year$this->month$this->day$this->hour$this->minute$this->second);
  178.                break;
  179.            case self::DB_TFORMAT:
  180.            case self::BD_TFORMAT:
  181.                $str sprintf('%02d:%02d:%02d'$this->hour$this->minute$this->second);
  182.                break;
  183.            case self::ISO8601_FORMAT:
  184.                $str sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ'$this->year$this->month$this->day$this->hour$this->minute$this->second);
  185.                break;
  186.            case self::TIMESTAMP_FORMAT:
  187.                $str =(string) mktime $this->hour$this->minute,$this->second $this->month$this->day$this->year );
  188.                break;
  189.            case self::RFC822_FORMAT:
  190.            case self::RFC2822_FORMAT:
  191.                $str date('r'mktime $this->hour$this->minute,$this->second $this->month$this->day$this->year ));
  192.                break;
  193.         }
  194.        return $str;
  195.     }
  196.  
  197.     /**
  198.      * read a string to extract date values
  199.      * @param string $str the string date
  200.      * @param int $format one of the class constant xxx_FORMAT, or -1 if it should use the default format
  201.      * @see jDateTime:$defaultFormat
  202.      */
  203.     function setFromString($str,$format=-1){
  204.         if($format==-1){
  205.             $format $this->defaultFormat;
  206.         }
  207.         $this->year = 0;
  208.         $this->month = 0;
  209.         $this->day = 0;
  210.         $this->hour = 0;
  211.         $this->minute = 0;
  212.         $this->second = 0;
  213.         $ok=false;
  214.  
  215.         switch($format){
  216.            case self::LANG_DFORMAT:
  217.                $lf jLocale::get('jelix~format.date_st');
  218.                if($res strptime $str$lf )){
  219.                    $ok=true;
  220.                    $this->year = $res['tm_year']+1900;
  221.                    $this->month = $res['tm_mon'+1;
  222.                    $this->day = $res['tm_mday'];
  223.                }
  224.                break;
  225.            case self::LANG_DTFORMAT:
  226.                $lf jLocale::get('jelix~format.datetime_st');
  227.                if($res strptime $str$lf )){
  228.                    $ok=true;
  229.                    $this->year = $res['tm_year'1900;
  230.                    $this->month = $res['tm_mon'1;
  231.                    $this->day = $res['tm_mday'];
  232.                    $this->hour = $res['tm_hour'];
  233.                    $this->minute = $res['tm_min'];
  234.                    $this->second = $res['tm_sec'];
  235.                }
  236.                break;
  237.            case self::LANG_TFORMAT:
  238.                $lf jLocale::get('jelix~format.time_st');
  239.                if($res strptime $str$lf )){
  240.                    $ok=true;
  241.                    $this->hour = $res['tm_hour'];
  242.                    $this->minute = $res['tm_min'];
  243.                    $this->second = $res['tm_sec'];
  244.                }
  245.                break;
  246.            case self::DB_DFORMAT:
  247.            case self::BD_DFORMAT:
  248.                if($res strptime$str"%Y-%m-%d" )){
  249.                    $ok=true;
  250.                    $this->year = $res['tm_year'1900;
  251.                    $this->month = $res['tm_mon'1;
  252.                    $this->day = $res['tm_mday'];
  253.                }
  254.                break;
  255.            case self::DB_DTFORMAT:
  256.            case self::BD_DTFORMAT:
  257.                if($res strptime$str"%Y-%m-%d %H:%M:%S" )){
  258.                    $ok=true;
  259.                    $this->year = $res['tm_year'1900;
  260.                    $this->month = $res['tm_mon'1;
  261.                    $this->day = $res['tm_mday'];
  262.                    $this->hour = $res['tm_hour'];
  263.                    $this->minute = $res['tm_min'];
  264.                    $this->second = $res['tm_sec'];
  265.                }
  266.                break;
  267.            case self::DB_TFORMAT:
  268.            case self::BD_TFORMAT:
  269.                if($res strptime$str"%H:%M:%S" )){
  270.                    $ok=true;
  271.                    $this->hour = $res['tm_hour'];
  272.                    $this->minute = $res['tm_min'];
  273.                    $this->second = $res['tm_sec'];
  274.                }
  275.                break;
  276.            case self::ISO8601_FORMAT:
  277.                if($ok=preg_match('/^(\d{4})(?:\-(\d{2})(?:\-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{2,3}))?)?(Z|([+\-])(\d{2}):(\d{2})))?)?)?$/'$str$match)){
  278.                     $c count($match)-1;
  279.                     $this->year = intval($match[1]);
  280.                     if($c<2break;
  281.                     $this->month = intval($match[2]);
  282.                     if($c<3break;
  283.                     $this->day = intval($match[3]);
  284.                     if($c<4break;
  285.                     $this->hour = intval($match[4]);
  286.                     $this->minute = intval($match[5]);
  287.                     if($match[6!= ''$this->second = intval($match[6]);
  288.                     if($match[8!= 'Z'){
  289.                         $d new jDuration(array('hour'=>$match[10],'minute'=>$match[11]));
  290.                         if($match[9== '+')
  291.                             $this->add($d);
  292.                         else
  293.                             $this->sub($d);
  294.                     }
  295.                }
  296.                break;
  297.            case self::TIMESTAMP_FORMAT:
  298.                $ok=true;
  299.                $t getdate intval($str) );
  300.                $this->year = $t['year'];
  301.                $this->month = $t['mon'];
  302.                $this->day = $t['mday'];
  303.                $this->hour = $t['hours'];
  304.                $this->minute = $t['minutes'];
  305.                $this->second = $t['seconds'];
  306.                break;
  307.            case self::RFC822_FORMAT:
  308.            case self::RFC2822_FORMAT:
  309.                // Note the "x" modifier, otherwise the pattern would look like
  310.                // obfuscated code.
  311.                $regexp "/^
  312.                      (?: (?P<nday> Mon | Tue | Wed | Thu | Fri | Sat | Sun) , )? \s+
  313.                      (?P<day>\d{1,2}) \s+
  314.                      (?P<nmonth> Jan | Feb | Mar | Apr | May | Jun |
  315.                                Jul | Aug | Sep | Oct | Nov | Dec) \s+
  316.                      (?P<year>\d{4}) \s+
  317.                      (?P<hour>\d{2}) : (?P<minute>\d{2}) (?: : (?P<second>\d{2}))? \s+
  318.                      (?P<tzsign>[+-]) (?P<tzhour>\d{2}) (?P<tzminute>\d{2})$/x";
  319.  
  320.                $english_months array("Jan""Feb""Mar""Apr""May""Jun",
  321.                    "Jul""Aug""Sep""Oct""Nov""Dec");
  322.  
  323.                $match array("year" => 0"month" => 0"day" => 0,
  324.                    "hour" => 0"minute" => 0"second" => 0"tzsign" => "+",
  325.                    "tzhour" => 0"tzminute" => 0);
  326.  
  327.                if($ok preg_match($regexp$str$match)){
  328.                    $this->year = intval($match['year']);
  329.                    $this->month = array_search($match['nmonth']$english_months1;
  330.                    $this->day = intval($match['day']);
  331.                    $this->hour = intval($match['hour']);
  332.                    $this->minute = intval($match['minute']);
  333.                    $this->second = intval($match['second']);
  334.  
  335.                    # Adjust according to the timezone, so that the stored time
  336.                    # corresponds to UTC.
  337.                    $tz new jDuration(array('hour'=>intval($match['tzhour']),
  338.                        'minute'=>intval($match['tzminute'])));
  339.                    if($match['tzsign'== '+'){
  340.                        $this->sub($tz);
  341.                    }
  342.                    else{
  343.                        $this->add($tz);
  344.                    }
  345.                }
  346.                break;
  347.         }
  348.  
  349.         return $ok && $this->_check();
  350.     }
  351.  
  352.     /**
  353.      * Add a duration to the date.
  354.      * You can specify the duration in a jDuration object or give each value of
  355.      * the duration.
  356.      * @param jDuration/int $year the duration value or a year with 4 digits
  357.      * @param int $month month with 2 digits
  358.      * @param int $day day with 2 digits
  359.      * @param int $hour hour with 2 digits
  360.      * @param int $minute minute with 2 digits
  361.      * @param int $second second with 2 digits
  362.      */
  363.     public function add($year$month=0$day=0$hour=0$minute=0$second=0{
  364.         if ($year instanceof jDuration{
  365.             $dt $year;
  366.         else {
  367.             $dt new jDuration(array("year" => $year"month" => $month,
  368.                 "day" => $day"hour" => $hour"minute" => $minute,
  369.                 "second" => $second));
  370.         }
  371.         $t mktime($this->hour$this->minute$this->second + $dt->seconds,
  372.              $this->month + $dt->months$this->day + $dt->days$this->year);
  373.  
  374.         $t getdate ($t);
  375.         $this->year = $t['year'];
  376.         $this->month = $t['mon'];
  377.         $this->day = $t['mday'];
  378.         $this->hour = $t['hours'];
  379.         $this->minute = $t['minutes'];
  380.         $this->second = $t['seconds'];
  381.     }
  382.  
  383.     /**
  384.      * substract a <b>duration</b> to the date
  385.      * You can specify the duration in a jDuration object or give each value of
  386.      * the duration.
  387.      * @param jDuration/int $year the duration value or a year with 4 digits
  388.      * @param int $month month with 2 digits
  389.      * @param int $day day with 2 digits
  390.      * @param int $hour hour with 2 digits
  391.      * @param int $minute minute with 2 digits
  392.      * @param int $second second with 2 digits
  393.      */
  394.     public function sub($year$month=0$day=0$hour=0$minute=0$second=0{
  395.         if ($year instanceof jDuration{
  396.             $dt $year;
  397.         else {
  398.             $dt new jDuration(array("year" => $year"month" => $month,
  399.                 "day" => $day"hour" => $hour"minute" => $minute,
  400.                 "second" => $second));
  401.         }
  402.         $dt->mult(-1);
  403.         $this->add($dt);
  404.     }
  405.  
  406.     /**
  407.      * to know the duration between two dates.
  408.      * @param jDateTime $dt  the date on which a sub will be made with the date on the current object
  409.      * @param bool $absolute 
  410.      * @return jDuration a jDuration object
  411.      */
  412.     public function durationTo($dt$absolute=true){
  413.         if($absolute){
  414.             $t mktime($dt->hour$dt->minute$dt->second,
  415.                 $dt->month$dt->day$dt->year)
  416.                 - mktime($this->hour$this->minute$this->second,
  417.                     $this->month$this->day$this->year);
  418.             return new jDuration($t);
  419.         }
  420.         else{
  421.             return new jDuration(array(
  422.                 "year" => $dt->year $this->year,
  423.                 "month" => $dt->month $this->month,
  424.                 "day" => $dt->day $this-> day,
  425.                 "hour" => $dt->hour $this->hour,
  426.                 "minute" => $dt->minute $this->minute,
  427.                 "second" => $dt->second $this->second
  428.             ));
  429.         }
  430.     }
  431.  
  432.     /**
  433.      * compare two date
  434.      * @param jDateTime $dt the date to compare
  435.      * @return integer -1 if $dt > $this, 0 if $dt = $this, 1 if $dt < $this
  436.      */
  437.     public function compareTo($dt){
  438.         $fields=array('year','month','day','hour','minute','second');
  439.         foreach($fields as $field){
  440.             if($dt->$field $this->$field)
  441.                 return -1;
  442.             if($dt->$field $this->$field)
  443.                 return 1;
  444.         }
  445.         return 0;
  446.     }
  447.  
  448.     /**
  449.     * set date to current datetime
  450.     */
  451.     public function now({
  452.         $this->year = intval(date('Y'));
  453.         $this->month = intval(date('m'));
  454.         $this->day = intval(date('d'));
  455.         $this->hour = intval(date('H'));
  456.         $this->minute = intval(date('i'));
  457.         $this->second = intval(date('s'));
  458.     }
  459. }

Documentation generated on Thu, 22 Mar 2012 22:15:12 +0100 by phpDocumentor 1.4.3