ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilDateTime.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4
5include_once('Services/Calendar/classes/class.ilDateTimeException.php');
6include_once('Services/Calendar/classes/class.ilTimeZone.php');
7
8
9define('IL_CAL_DATETIME', 1);
10define('IL_CAL_DATE', 2);
11define('IL_CAL_UNIX', 3);
12define('IL_CAL_FKT_DATE', 4);
13define('IL_CAL_FKT_GETDATE', 5);
14define('IL_CAL_TIMESTAMP', 6);
15define('IL_CAL_ISO_8601', 7);
16
17define('IL_CAL_YEAR', 'year');
18define('IL_CAL_MONTH', 'month');
19define('IL_CAL_WEEK', 'week');
20define('IL_CAL_DAY', 'day');
21define('IL_CAL_HOUR', 'hour');
22define('IL_CAL_SECOND', 'second');
23
24
34{
35 const YEAR = 'year';
36 const MONTH = 'month';
37 const WEEK = 'week';
38 const DAY = 'day';
39 const HOUR = 'hour';
40 const MINUTE = 'minute';
41 const SECOND = 'second';
42
46 protected $log;
47
48 protected $timezone = null;
49 protected $default_timezone = null;
50
54 protected $dt_obj; // [DateTime]
55
56
57
68 public function __construct($a_date = null, $a_format = 0, $a_tz = '')
69 {
70 global $DIC;
71
72 $this->log = $DIC->logger()->cal();
73
74 try {
75 $this->timezone = ilTimeZone::_getInstance($a_tz);
76 $this->default_timezone = ilTimeZone::_getInstance('');
77
78 $this->setDate($a_date, $a_format);
79 } catch (ilTimeZoneException $exc) {
80 $this->log->warning($exc->getMessage());
81 throw new ilDateTimeException('Unsupported timezone given. Timezone: ' . $a_tz);
82 }
83 }
84
85 public function __clone()
86 {
87 if ($this->dt_obj) {
88 $this->dt_obj = clone $this->dt_obj;
89 }
90 }
91
92 public function __sleep()
93 {
94 return array('timezone', 'default_timezone', 'dt_obj');
95 }
96
97 public function __wakeup()
98 {
99 global $DIC;
100
101 $this->log = $DIC->logger()->cal();
102 }
103
109 public function isNull()
110 {
111 return !($this->dt_obj instanceof DateTime);
112 }
113
121 public function switchTimeZone($a_timezone_identifier = '')
122 {
123 try {
124 $this->timezone = ilTimeZone::_getInstance($a_timezone_identifier);
125 return true;
126 } catch (ilTimeZoneException $e) {
127 $this->log->warning('Unsupported timezone given: ' . $a_timezone_identifier);
128 throw new ilDateTimeException('Unsupported timezone given. Timezone: ' . $a_timezone_identifier);
129 }
130 }
131
138 public function getTimeZoneIdentifier()
139 {
140 return $this->timezone->getIdentifier();
141 }
142
157 public static function _before(ilDateTime $start, ilDateTime $end, $a_compare_field = '', $a_tz = '')
158 {
159 if ($start->isNull() || $end->isNull()) {
160 return false;
161 }
162
163 switch ($a_compare_field) {
164 case IL_CAL_YEAR:
165 return $start->get(IL_CAL_FKT_DATE, 'Y', $a_tz) < $end->get(IL_CAL_FKT_DATE, 'Y', $a_tz);
166
167 case IL_CAL_MONTH:
168 return (int) $start->get(IL_CAL_FKT_DATE, 'Ym', $a_tz) < $end->get(IL_CAL_FKT_DATE, 'Ym', $a_tz);
169
170 case IL_CAL_DAY:
171 return (int) $start->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz) < $end->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz);
172
173 case '':
174 default:
175 return $start->dt_obj < $end->dt_obj;
176
177 }
178 }
179
192 public static function _equals(ilDateTime $start, ilDateTime $end, $a_compare_field = '', $a_tz = '')
193 {
194 if ($start->isNull() || $end->isNull()) {
195 return false;
196 }
197
198 switch ($a_compare_field) {
199 case IL_CAL_YEAR:
200 return $start->get(IL_CAL_FKT_DATE, 'Y', $a_tz) == $end->get(IL_CAL_FKT_DATE, 'Y', $a_tz);
201
202 case IL_CAL_MONTH:
203 return (int) $start->get(IL_CAL_FKT_DATE, 'Ym', $a_tz) == $end->get(IL_CAL_FKT_DATE, 'Ym', $a_tz);
204
205 case IL_CAL_DAY:
206 return (int) $start->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz) == $end->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz);
207
208 case '':
209 default:
210 return $start->dt_obj == $end->dt_obj;
211
212 }
213 }
214
227 public static function _after(ilDateTime $start, ilDateTime $end, $a_compare_field = '', $a_tz = '')
228 {
229 if ($start->isNull() || $end->isNull()) {
230 return false;
231 }
232
233 switch ($a_compare_field) {
234 case IL_CAL_YEAR:
235 return $start->get(IL_CAL_FKT_DATE, 'Y', $a_tz) > $end->get(IL_CAL_FKT_DATE, 'Y', $a_tz);
236
237 case IL_CAL_MONTH:
238 return (int) $start->get(IL_CAL_FKT_DATE, 'Ym', $a_tz) > $end->get(IL_CAL_FKT_DATE, 'Ym', $a_tz);
239
240 case IL_CAL_DAY:
241 return (int) $start->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz) > $end->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz);
242
243 case '':
244 default:
245 return $start->dt_obj > $end->dt_obj;
246
247 }
248 }
249
258 public static function _within(ilDateTime $dt, ilDateTime $start, ilDateTime $end, $a_compare_field = '', $a_tz = '')
259 {
260 return
261 (ilDateTime::_after($dt, $start, $a_compare_field, $a_tz) or ilDateTime::_equals($dt, $start, $a_compare_field, $a_tz)) &&
262 (ilDateTime::_before($dt, $end, $a_compare_field, $a_tz) or ilDateTime::_equals($dt, $end, $a_compare_field, $a_tz));
263 }
264
273 public function increment($a_type, $a_count = 1)
274 {
275 if ($this->isNull()) {
276 return;
277 }
278
279 $sub = ($a_count < 0);
280 $count_str = abs($a_count);
281
282 switch ($a_type) {
283 case self::YEAR:
284 $count_str .= 'year';
285 break;
286
287 case self::MONTH:
288 $count_str .= 'month';
289 break;
290
291 case self::WEEK:
292 $count_str .= 'week';
293 break;
294
295 case self::DAY:
296 $count_str .= 'day';
297 break;
298
299 case self::HOUR:
300 $count_str .= 'hour';
301 break;
302
303 case self::MINUTE:
304 $count_str .= 'minute';
305 break;
306
307 case self::SECOND:
308 $count_str .= 'second';
309 break;
310 }
311
312 $interval = date_interval_create_from_date_string($count_str);
313 if (!$sub) {
314 $this->dt_obj->add($interval);
315 } else {
316 $this->dt_obj->sub($interval);
317 }
318
319 // ???
320 return $this->getUnixTime();
321 }
322
329 public function getUnixTime()
330 {
331 if (!$this->isNull()) {
332 return $this->dt_obj->getTimestamp();
333 }
334 }
335
342 public function getUTCOffset()
343 {
344 if (!$this->isNull()) {
345 // already correct/current timezone?
346 $offset = $this->dt_obj->getOffset();
347
348 // TODO: This is wrong: calculate UTC offset of given date
349 // $offset = mktime(0,0,0,2,1,1970) - gmmktime(0,0,0,2,1,1970);
350 }
351 return $offset;
352 }
353
354 protected function parsePartsToDate($a_year, $a_month, $a_day, $a_hour = null, $a_min = null, $a_sec = null, $a_timezone = null)
355 {
356 $a_year = (int) $a_year;
357 $a_month = (int) $a_month;
358 $a_day = (int) $a_day;
359
360 if (!$a_year) {
361 return;
362 }
363
364 try {
365 $a_hour = (int) $a_hour;
366 $a_min = (int) $a_min;
367 $a_sec = (int) $a_sec;
368
369 $format = $a_year . '-' . $a_month . '-' . $a_day;
370
371 if ($a_hour !== null) {
372 $format .= ' ' . (int) $a_hour . ':' . (int) $a_min . ':' . (int) $a_sec;
373
374 // use current timezone if no other given
375 if (!$a_timezone) {
376 $a_timezone = $this->getTimeZoneIdentifier();
377 }
378
379 $date = new DateTime($format, new DateTimeZone($a_timezone));
380 } else {
381 $date = new DateTime($format);
382 }
383 } catch (Exception $ex) {
384 // :TODO: do anything?
385 }
386 return ($date instanceof DateTime)
387 ? $date
388 : null;
389 }
390
401 public function setDate($a_date, $a_format)
402 {
403 $this->dt_obj = null;
404
405 if (!$a_date) {
406 return;
407 }
408
409 switch ($a_format) {
410 case IL_CAL_UNIX:
411 try {
412 $this->dt_obj = new DateTime('@' . $a_date);
413 $this->dt_obj->setTimezone(new DateTimeZone($this->getTimeZoneIdentifier()));
414 } catch (Exception $ex) {
415 $message = 'Cannot parse date: ' . $a_date . ' with format ' . $a_format;
416 $this->log->warning($message);
417 throw new ilDateTimeException($message);
418 }
419 break;
420
421 case IL_CAL_DATETIME:
422 $matches = preg_match('/^(\d{4})-?(\d{2})-?(\d{2})([T\s]?(\d{2}):?(\d{2}):?(\d{2})(\.\d+)?(Z|[\+\-]\d{2}:?\d{2})?)$/i', $a_date, $d_parts);
423 if ($matches < 1) {
424 $this->log->warning('Cannot parse date: ' . $a_date);
425 $this->log->warning(print_r($matches, true));
426 $this->log->logStack(ilLogLevel::WARNING);
427 throw new ilDateTimeException('Cannot parse date: ' . $a_date);
428 }
429
430 $tz_id = ($d_parts[9] == 'Z')
431 ? 'UTC'
432 : $this->getTimeZoneIdentifier();
433 $this->dt_obj = $this->parsePartsToDate(
434 $d_parts[1],
435 $d_parts[2],
436 $d_parts[3],
437 $d_parts[5],
438 $d_parts[6],
439 $d_parts[7],
440 $tz_id
441 );
442 break;
443
444 case IL_CAL_DATE:
445 try {
446 // Pure dates are not timezone sensible.
447 $this->dt_obj = new DateTime($a_date, new DateTimeZone('UTC'));
448 } catch (Exception $ex) {
449 $this->log->warning('Cannot parse date : ' . $a_date);
450 throw new ilDateTimeException('Cannot parse date: ' . $a_date);
451 }
452 break;
453
455 // Format like getdate parameters
456 $this->dt_obj = $this->parsePartsToDate(
457 $a_date['year'],
458 $a_date['mon'],
459 $a_date['mday'],
460 $a_date['hours'],
461 $a_date['minutes'],
462 $a_date['seconds'],
463 $this->getTimeZoneIdentifier()
464 );
465 break;
466
467 case IL_CAL_TIMESTAMP:
468 if (preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $a_date, $d_parts) == false) {
469 $this->log->warning('Cannot parse date: ' . $a_date);
470 throw new ilDateTimeException('Cannot parse date.');
471 }
472 $this->dt_obj = $this->parsePartsToDate(
473 $d_parts[1],
474 $d_parts[2],
475 $d_parts[3],
476 $d_parts[4],
477 $d_parts[5],
478 $d_parts[6],
479 $this->getTimeZoneIdentifier()
480 );
481 break;
482
483 case IL_CAL_ISO_8601:
484 $this->dt_obj = DateTime::createFromFormat(
485 DateTime::ISO8601,
486 $a_date,
487 new DateTimeZone($this->getTimeZoneIdentifier())
488 );
489 break;
490 }
491
492 // remove set timezone since it does not influence the internal date.
493 // the tz must be passed in the moment of the creation of the date object.
494 return true;
495 }
496
506 public function get($a_format, $a_format_str = '', $a_tz = '')
507 {
508 if ($this->isNull()) {
509 return;
510 }
511
512 if ($a_tz) {
513 try {
515 } catch (ilTimeZoneException $exc) {
516 $this->log->warning('Invalid timezone given. Timezone: ' . $a_tz);
517 }
518 } else {
520 }
521
522 $out_date = clone($this->dt_obj);
523 $out_date->setTimezone(new DateTimeZone($timezone->getIdentifier()));
524
525 switch ($a_format) {
526 case IL_CAL_UNIX:
527 // timezone unrelated
528 $date = $this->getUnixTime();
529 break;
530
531 case IL_CAL_DATE:
532 $date = $out_date->format('Y-m-d');
533 break;
534
535 case IL_CAL_DATETIME:
536 $date = $out_date->format('Y-m-d H:i:s');
537 break;
538
539 case IL_CAL_FKT_DATE:
540 $date = $out_date->format($a_format_str);
541 break;
542
544 $date = array(
545 'seconds' => (int) $out_date->format('s')
546 ,'minutes' => (int) $out_date->format('i')
547 ,'hours' => (int) $out_date->format('G')
548 ,'mday' => (int) $out_date->format('j')
549 ,'wday' => (int) $out_date->format('w')
550 ,'mon' => (int) $out_date->format('n')
551 ,'year' => (int) $out_date->format('Y')
552 ,'yday' => (int) $out_date->format('z')
553 ,'weekday' => $out_date->format('l')
554 ,'month' => $out_date->format('F')
555 ,'isoday' => (int) $out_date->format('N')
556 );
557 break;
558
559 case IL_CAL_ISO_8601:
560 $date = $out_date->format('c');
561 break;
562
563 case IL_CAL_TIMESTAMP:
564 $date = $out_date->format('YmdHis');
565 break;
566 }
567
568 return $date;
569 }
570
579 public function __toString()
580 {
581 return $this->get(IL_CAL_DATETIME) . '<br>';
582 }
583}
An exception for terminatinating execution or to throw for unit testing.
const IL_CAL_FKT_GETDATE
const IL_CAL_DATE
const IL_CAL_ISO_8601
const IL_CAL_TIMESTAMP
const IL_CAL_UNIX
const IL_CAL_YEAR
const IL_CAL_DATETIME
const IL_CAL_MONTH
const IL_CAL_FKT_DATE
const IL_CAL_DAY
Class for DateTime exceptions.
@classDescription Date and time handling
static _equals(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
Check if two date are equal.
switchTimeZone($a_timezone_identifier='')
Switch timezone.
static _after(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
compare two dates and check start is after end This method does not consider tz offsets.
get($a_format, $a_format_str='', $a_tz='')
get formatted date
isNull()
Check if a date is null (Datetime == '0000-00-00 00:00:00', unixtime == 0,...)
__construct($a_date=null, $a_format=0, $a_tz='')
Create new date object.
getTimeZoneIdentifier()
get timezone identifier
getUTCOffset()
get UTC offset
__toString()
to string for date time objects Output is user time zone
getUnixTime()
get unix time
static _within(ilDateTime $dt, ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
Check whether an date is within a date duration given by start and end.
increment($a_type, $a_count=1)
increment
static _before(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
compare two dates and check start is before end This method does not consider tz offsets.
parsePartsToDate($a_year, $a_month, $a_day, $a_hour=null, $a_min=null, $a_sec=null, $a_timezone=null)
setDate($a_date, $a_format)
Set date.
Class for TimeZone exceptions.
static _getInstance($a_tz='')
get instance by timezone
global $DIC
Definition: goto.php:24
$format
Definition: metadata.php:218
$message
Definition: xapiexit.php:14