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

Documentation generated on Wed, 07 Sep 2011 13:47:10 +0200 by phpDocumentor 1.4.3