00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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;
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
00062 public static function makeFromWeek($weekNumber, $year = null)
00063 {
00064 if (!$year)
00065 $year = date('Y');
00066
00067 Assert::isTrue(
00068 ($weekNumber > 0)
00069 && ($weekNumber < 53)
00070 );
00071
00072 $date =
00073 new self(
00074 date(
00075 self::getFormat(),
00076 mktime(
00077 0, 0, 0, 1, 1, $year
00078 )
00079 )
00080 );
00081
00082 $days = ($weekNumber * 7);
00083
00084 return $date->modify("+{$days} day");
00085 }
00086
00087 public static function dayDifference(Date $left, Date $right)
00088 {
00089 return
00090 gregoriantojd(
00091 $right->getMonth(),
00092 $right->getDay(),
00093 $right->getYear()
00094 )
00095 - gregoriantojd(
00096 $left->getMonth(),
00097 $left->getDay(),
00098 $left->getYear()
00099 );
00100 }
00101
00102 public static function compare(Date $left, Date $right)
00103 {
00104 if ($left->int == $right->int)
00105 return 0;
00106 else
00107 return ($left->int > $right->int ? 1 : -1);
00108 }
00109
00110 public function __construct($date)
00111 {
00112 if (is_int($date) || is_numeric($date)) {
00113 $this->int = $date;
00114 $this->string = date($this->getFormat(), $date);
00115 } elseif ($date && is_string($date))
00116 $this->stringImport($date);
00117
00118 if ($this->string === null) {
00119 throw new WrongArgumentException(
00120 "strange input given - '{$date}'"
00121 );
00122 }
00123
00124 $this->import($this->string);
00125 }
00126
00127 public function toStamp()
00128 {
00129 return $this->int;
00130 }
00131
00132 public function toDate($delimiter = '-')
00133 {
00134 return
00135 $this->year
00136 .$delimiter
00137 .$this->month
00138 .$delimiter
00139 .$this->day;
00140 }
00141
00142 public function getYear()
00143 {
00144 return $this->year;
00145 }
00146
00147 public function getMonth()
00148 {
00149 return $this->month;
00150 }
00151
00152 public function getDay()
00153 {
00154 return $this->day;
00155 }
00156
00157 public function getWeek()
00158 {
00159 return date('W', $this->int);
00160 }
00161
00162 public function getWeekDay()
00163 {
00164 return strftime('%w', $this->int);
00165 }
00166
00170 public function spawn($modification = null)
00171 {
00172 $child = new $this($this->string);
00173
00174 if ($modification)
00175 return $child->modify($modification);
00176
00177 return $child;
00178 }
00179
00184 public function modify($string)
00185 {
00186 try {
00187 $time = strtotime($string, $this->int);
00188
00189 if ($time === false)
00190 throw new WrongArgumentException(
00191 "modification yielded false '{$string}'"
00192 );
00193
00194 $this->int = $time;
00195 $this->string = date($this->getFormat(), $time);
00196 $this->import($this->string);
00197 } catch (BaseException $e) {
00198 throw new WrongArgumentException(
00199 "wrong time string '{$string}'"
00200 );
00201 }
00202
00203 return $this;
00204 }
00205
00206 public function getDayStartStamp()
00207 {
00208 return
00209 mktime(
00210 0, 0, 0,
00211 $this->month,
00212 $this->day,
00213 $this->year
00214 );
00215 }
00216
00217 public function getDayEndStamp()
00218 {
00219 return
00220 mktime(
00221 23, 59, 59,
00222 $this->month,
00223 $this->day,
00224 $this->year
00225 );
00226 }
00227
00231 public function getFirstDayOfWeek($weekStart = Date::WEEKDAY_MONDAY)
00232 {
00233 return $this->spawn(
00234 '-'.((7 + $this->getWeekDay() - $weekStart) % 7).' days'
00235 );
00236 }
00237
00241 public function getLastDayOfWeek($weekStart = Date::WEEKDAY_MONDAY)
00242 {
00243 return $this->spawn(
00244 '+'.((13 - $this->getWeekDay() + $weekStart) % 7).' days'
00245 );
00246 }
00247
00248 public function toString()
00249 {
00250 return $this->string;
00251 }
00252
00253 public function toDialectString(Dialect $dialect)
00254 {
00255
00256 return $dialect->quoteValue($this->toString());
00257 }
00258
00262 public function toISOString()
00263 {
00264 return $this->toString();
00265 }
00266
00267 protected static function getFormat()
00268 {
00269 return 'Y-m-d';
00270 }
00271
00272 protected function import($string)
00273 {
00274 list($this->year, $this->month, $this->day) =
00275 explode('-', $string, 3);
00276
00277 if (!$this->month || !$this->day)
00278 throw new WrongArgumentException(
00279 'month and day must not be zero'
00280 );
00281
00282 $this->string =
00283 sprintf(
00284 '%04d-%02d-%02d',
00285 $this->year,
00286 $this->month,
00287 $this->day
00288 );
00289
00290 list($this->year, $this->month, $this->day) =
00291 explode('-', $this->string, 3);
00292 }
00293
00294 protected function stringImport($string)
00295 {
00296 $this->int = strtotime($string);
00297
00298 $matches = array();
00299
00300 if (
00301 preg_match('/^(\d{1,4})-(\d{1,2})-(\d{1,2})$/', $string, $matches)
00302 ) {
00303 if (checkdate($matches[2], $matches[3], $matches[1]))
00304 $this->string = $string;
00305
00306 } elseif ($this->int !== false)
00307 $this->string = date($this->getFormat(), $this->int);
00308 }
00309 }
00310 ?>