Date.class.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************************
00003  *   Copyright (C) 2006-2009 by Garmonbozia Research Group                 *
00004  *   Anton E. Lebedevich, Konstantin V. Arkhipov                           *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU Lesser General Public License as        *
00008  *   published by the Free Software Foundation; either version 3 of the    *
00009  *   License, or (at your option) any later version.                       *
00010  *                                                                         *
00011  ***************************************************************************/
00012 /* $Id$ */
00013 
00021     class Date implements Stringable, DialectString
00022     {
00023         const WEEKDAY_MONDAY    = 1;
00024         const WEEKDAY_TUESDAY   = 2;
00025         const WEEKDAY_WEDNESDAY = 3;
00026         const WEEKDAY_THURSDAY  = 4;
00027         const WEEKDAY_FRIDAY    = 5;
00028         const WEEKDAY_SATURDAY  = 6;
00029         const WEEKDAY_SUNDAY    = 0; // because strftime('%w') is 0 on Sunday
00030         
00031         protected $string   = null;
00032         protected $int      = null;
00033         
00034         protected $year     = null;
00035         protected $month    = null;
00036         protected $day      = null;
00037         
00041         public static function create($date)
00042         {
00043             return new self($date);
00044         }
00045         
00046         public static function today($delimiter = '-')
00047         {
00048             return date("Y{$delimiter}m{$delimiter}d");
00049         }
00050         
00054         public static function makeToday()
00055         {
00056             return new self(self::today());
00057         }
00058         
00064         public static function makeFromWeek($weekNumber, $year = null)
00065         {
00066             if (!$year)
00067                 $year = date('Y');
00068 
00069             Assert::isTrue(
00070                 ($weekNumber > 0)
00071                 && ($weekNumber <= self::getWeekCountInYear($year))
00072             );
00073             
00074             $date =
00075                 new self(
00076                     date(
00077                         self::getFormat(),
00078                         mktime(
00079                             0, 0, 0, 1, 1, $year
00080                         )
00081                     )
00082                 );
00083             
00084             $days =
00085                 (
00086                     (
00087                         $weekNumber - 1
00088                         + (self::getWeekCountInYear($year - 1) == 53 ? 1 : 0)
00089                     )
00090                     * 7
00091                 ) + 1 - $date->getWeekDay();
00092             
00093             return $date->modify("+{$days} day");
00094         }
00095         
00096         public static function dayDifference(Date $left, Date $right)
00097         {
00098             return
00099                 gregoriantojd(
00100                     $right->getMonth(),
00101                     $right->getDay(),
00102                     $right->getYear()
00103                 )
00104                 - gregoriantojd(
00105                     $left->getMonth(),
00106                     $left->getDay(),
00107                     $left->getYear()
00108                 );
00109         }
00110         
00111         public static function compare(Date $left, Date $right)
00112         {
00113             if ($left->int == $right->int)
00114                 return 0;
00115             else
00116                 return ($left->int > $right->int ? 1 : -1);
00117         }
00118 
00119         public static function getWeekCountInYear($year)
00120         {
00121             return date('W', mktime(0, 0, 0, 12, 31, $year));
00122         }
00123 
00124         public function __construct($date)
00125         {
00126             if (is_int($date) || is_numeric($date)) { // unix timestamp
00127                 $this->string = date($this->getFormat(), $date);
00128             } elseif ($date && is_string($date))
00129                 $this->stringImport($date);
00130             
00131             if ($this->string === null) {
00132                 throw new WrongArgumentException(
00133                     "strange input given - '{$date}'"
00134                 );
00135             }
00136             
00137             $this->import($this->string);
00138             $this->buildInteger();
00139         }
00140         
00141         public function toStamp()
00142         {
00143             return $this->int;
00144         }
00145         
00146         public function toDate($delimiter = '-')
00147         {
00148             return
00149                 $this->year
00150                 .$delimiter
00151                 .$this->month
00152                 .$delimiter
00153                 .$this->day;
00154         }
00155         
00156         public function getYear()
00157         {
00158             return $this->year;
00159         }
00160 
00161         public function getMonth()
00162         {
00163             return $this->month;
00164         }
00165 
00166         public function getDay()
00167         {
00168             return $this->day;
00169         }
00170         
00171         public function getWeek()
00172         {
00173             return date('W', $this->int);
00174         }
00175 
00176         public function getWeekDay()
00177         {
00178             return strftime('%w', $this->int);
00179         }
00180         
00184         public function spawn($modification = null)
00185         {
00186             $child = new $this($this->string);
00187             
00188             if ($modification)
00189                 return $child->modify($modification);
00190             
00191             return $child;
00192         }
00193         
00198         public function modify($string)
00199         {
00200             try {
00201                 $time = strtotime($string, $this->int);
00202                 
00203                 if ($time === false)
00204                     throw new WrongArgumentException(
00205                         "modification yielded false '{$string}'"
00206                     );
00207                 
00208                 $this->int = $time;
00209                 $this->string = date($this->getFormat(), $time);
00210                 $this->import($this->string);
00211             } catch (BaseException $e) {
00212                 throw new WrongArgumentException(
00213                     "wrong time string '{$string}'"
00214                 );
00215             }
00216             
00217             return $this;
00218         }
00219         
00220         public function getDayStartStamp()
00221         {
00222             return
00223                 mktime(
00224                     0, 0, 0,
00225                     $this->month,
00226                     $this->day,
00227                     $this->year
00228                 );
00229         }
00230         
00231         public function getDayEndStamp()
00232         {
00233             return
00234                 mktime(
00235                     23, 59, 59,
00236                     $this->month,
00237                     $this->day,
00238                     $this->year
00239                 );
00240         }
00241         
00245         public function getFirstDayOfWeek($weekStart = Date::WEEKDAY_MONDAY)
00246         {
00247             return $this->spawn(
00248                 '-'.((7 + $this->getWeekDay() - $weekStart) % 7).' days'
00249             );
00250         }
00251         
00255         public function getLastDayOfWeek($weekStart = Date::WEEKDAY_MONDAY)
00256         {
00257             return $this->spawn(
00258                 '+'.((13 - $this->getWeekDay() + $weekStart) % 7).' days'
00259             );
00260         }
00261         
00262         public function toString()
00263         {
00264             return $this->string;
00265         }
00266         
00267         public function toDialectString(Dialect $dialect)
00268         {
00269             // there are no known differences yet
00270             return $dialect->quoteValue($this->toString());
00271         }
00272         
00276         public function toIsoString()
00277         {
00278             return $this->toString();
00279         }
00280         
00284         public function toTimestamp()
00285         {
00286             return Timestamp::create($this->toStamp());
00287         }
00288         
00289         protected static function getFormat()
00290         {
00291             return 'Y-m-d';
00292         }
00293         
00294         /* void */ protected function import($string)
00295         {
00296             list($this->year, $this->month, $this->day) =
00297                 explode('-', $string, 3);
00298             
00299             if (!$this->month || !$this->day)
00300                 throw new WrongArgumentException(
00301                     'month and day must not be zero'
00302                 );
00303             
00304             $this->string =
00305                 sprintf(
00306                     '%04d-%02d-%02d',
00307                     $this->year,
00308                     $this->month,
00309                     $this->day
00310                 );
00311             
00312             list($this->year, $this->month, $this->day) =
00313                 explode('-', $this->string, 3);
00314         }
00315         
00316         /* void */ protected function stringImport($string)
00317         {
00318             $matches = array();
00319             
00320             if (
00321                 preg_match('/^(\d{1,4})-(\d{1,2})-(\d{1,2})$/', $string, $matches)
00322             ) {
00323                 if (checkdate($matches[2], $matches[3], $matches[1]))
00324                     $this->string = $string;
00325                 
00326             } elseif (($stamp = strtotime($string)) !== false)
00327                 $this->string = date($this->getFormat(), $stamp);
00328         }
00329         
00330         /* void */ protected function buildInteger()
00331         {
00332             $this->int =
00333                 mktime(
00334                     0, 0, 0,
00335                     $this->month,
00336                     $this->day,
00337                     $this->year
00338                 );
00339         }
00340     }
00341 ?>