ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilDateTime.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22const IL_CAL_DATE = 2;
23const IL_CAL_UNIX = 3;
28
29const IL_CAL_YEAR = 'year';
30const IL_CAL_MONTH = 'month';
31const IL_CAL_WEEK = 'week';
32const IL_CAL_DAY = 'day';
33const IL_CAL_HOUR = 'hour';
34const IL_CAL_SECOND = 'second';
35
43{
44 public const YEAR = 'year';
45 public const MONTH = 'month';
46 public const WEEK = 'week';
47 public const DAY = 'day';
48 public const HOUR = 'hour';
49 public const MINUTE = 'minute';
50 public const SECOND = 'second';
51
52 protected ilLogger $log;
53 protected ?ilTimeZone $timezone = null;
54 protected ?ilTimeZone $default_timezone = null;
55 protected ?DateTime $dt_obj = null;
56
64 public function __construct($a_date = null, int $a_format = 0, string $a_tz = '')
65 {
66 global $DIC;
67
68 $this->log = $DIC->logger()->cal();
69
70 try {
71 $this->timezone = ilTimeZone::_getInstance($a_tz);
72 $this->default_timezone = ilTimeZone::_getInstance('');
73 $this->setDate($a_date, $a_format);
74 } catch (ilTimeZoneException $exc) {
75 $this->log->warning($exc->getMessage());
76 throw new ilDateTimeException('Unsupported timezone given. Timezone: ' . $a_tz);
77 }
78 }
79
80 public function __clone()
81 {
82 if ($this->dt_obj) {
83 $this->dt_obj = clone $this->dt_obj;
84 }
85 }
86
87 public function __sleep()
88 {
89 return array('timezone', 'default_timezone', 'dt_obj');
90 }
91
92 public function __wakeup()
93 {
94 global $DIC;
95 $this->log = $DIC->logger()->cal();
96 }
97
102 public function isNull(): bool
103 {
104 return !($this->dt_obj instanceof DateTime);
105 }
106
112 public function switchTimeZone(string $a_timezone_identifier = ''): void
113 {
114 try {
115 $this->timezone = ilTimeZone::_getInstance($a_timezone_identifier);
116 return;
117 } catch (ilTimeZoneException $e) {
118 $this->log->warning('Unsupported timezone given: ' . $a_timezone_identifier);
119 throw new ilDateTimeException('Unsupported timezone given. Timezone: ' . $a_timezone_identifier);
120 }
121 }
122
123 public function getTimeZoneIdentifier(): string
124 {
125 return $this->timezone->getIdentifier();
126 }
127
138 public static function _before(
139 ilDateTime $start,
140 ilDateTime $end,
141 string $a_compare_field = '',
142 string $a_tz = ''
143 ): bool {
144 if ($start->isNull() || $end->isNull()) {
145 return false;
146 }
147
148 switch ($a_compare_field) {
149 case IL_CAL_YEAR:
150 return $start->get(IL_CAL_FKT_DATE, 'Y', $a_tz) < $end->get(IL_CAL_FKT_DATE, 'Y', $a_tz);
151
152 case IL_CAL_MONTH:
153 return (int) $start->get(IL_CAL_FKT_DATE, 'Ym', $a_tz) < $end->get(IL_CAL_FKT_DATE, 'Ym', $a_tz);
154
155 case IL_CAL_DAY:
156 return (int) $start->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz) < $end->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz);
157
158 case '':
159 default:
160 return $start->dt_obj < $end->dt_obj;
161 }
162 }
163
172 public static function _equals(
173 ilDateTime $start,
174 ilDateTime $end,
175 string $a_compare_field = '',
176 string $a_tz = ''
177 ): bool {
178 if ($start->isNull() || $end->isNull()) {
179 return false;
180 }
181
182 switch ($a_compare_field) {
183 case IL_CAL_YEAR:
184 return $start->get(IL_CAL_FKT_DATE, 'Y', $a_tz) == $end->get(IL_CAL_FKT_DATE, 'Y', $a_tz);
185
186 case IL_CAL_MONTH:
187 return (int) $start->get(IL_CAL_FKT_DATE, 'Ym', $a_tz) == $end->get(IL_CAL_FKT_DATE, 'Ym', $a_tz);
188
189 case IL_CAL_DAY:
190 return (int) $start->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz) == $end->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz);
191
192 case '':
193 default:
194 return $start->dt_obj == $end->dt_obj;
195 }
196 }
197
209 public static function _after(
210 ilDateTime $start,
211 ilDateTime $end,
212 string $a_compare_field = '',
213 string $a_tz = ''
214 ): bool {
215 if ($start->isNull() || $end->isNull()) {
216 return false;
217 }
218
219 switch ($a_compare_field) {
220 case IL_CAL_YEAR:
221 return $start->get(IL_CAL_FKT_DATE, 'Y', $a_tz) > $end->get(IL_CAL_FKT_DATE, 'Y', $a_tz);
222
223 case IL_CAL_MONTH:
224 return (int) $start->get(IL_CAL_FKT_DATE, 'Ym', $a_tz) > $end->get(IL_CAL_FKT_DATE, 'Ym', $a_tz);
225
226 case IL_CAL_DAY:
227 return (int) $start->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz) > $end->get(IL_CAL_FKT_DATE, 'Ymd', $a_tz);
228
229 case '':
230 default:
231 return $start->dt_obj > $end->dt_obj;
232 }
233 }
234
238 public static function _within(
239 ilDateTime $dt,
240 ilDateTime $start,
241 ilDateTime $end,
242 string $a_compare_field = '',
243 string $a_tz = ''
244 ): bool {
245 return
246 (ilDateTime::_after($dt, $start, $a_compare_field, $a_tz) or ilDateTime::_equals(
247 $dt,
248 $start,
249 $a_compare_field,
250 $a_tz
251 )) &&
252 (ilDateTime::_before($dt, $end, $a_compare_field, $a_tz) or ilDateTime::_equals(
253 $dt,
254 $end,
255 $a_compare_field,
256 $a_tz
257 ));
258 }
259
266 public function increment(string $a_type, int $a_count = 1): ?int
267 {
268 if ($this->isNull()) {
269 return null;
270 }
271
272 $sub = ($a_count < 0);
273 $count_str = abs($a_count);
274
275 switch ($a_type) {
276 case self::YEAR:
277 $count_str .= 'year';
278 break;
279
280 case self::MONTH:
281 $count_str .= 'month';
282 break;
283
284 case self::WEEK:
285 $count_str .= 'week';
286 break;
287
288 case self::DAY:
289 $count_str .= 'day';
290 break;
291
292 case self::HOUR:
293 $count_str .= 'hour';
294 break;
295
296 case self::MINUTE:
297 $count_str .= 'minute';
298 break;
299
300 case self::SECOND:
301 $count_str .= 'second';
302 break;
303 }
304
305 $interval = date_interval_create_from_date_string($count_str);
306 if (!$sub) {
307 $this->dt_obj->add($interval);
308 } else {
309 $this->dt_obj->sub($interval);
310 }
311 return $this->getUnixTime();
312 }
313
314 public function getUnixTime(): ?int
315 {
316 if (!$this->isNull()) {
317 return $this->dt_obj->getTimestamp();
318 }
319 return null;
320 }
321
322 protected function parsePartsToDate(
323 int $a_year,
324 int $a_month,
325 int $a_day,
326 ?int $a_hour = null,
327 ?int $a_min = null,
328 ?int $a_sec = null,
329 ?string $a_timezone = null
330 ): ?DateTime {
331 $a_year = $a_year;
332 $a_month = $a_month;
333 $a_day = $a_day;
334
335 if (!$a_year) {
336 return null;
337 }
338 $date = null;
339 try {
340 $a_hour = (int) $a_hour;
341 $a_min = (int) $a_min;
342 $a_sec = (int) $a_sec;
343
344 $format = $a_year . '-' . $a_month . '-' . $a_day;
345
346 if ($a_hour !== null) {
347 $format .= ' ' . $a_hour . ':' . $a_min . ':' . $a_sec;
348
349 // use current timezone if no other given
350 if (!$a_timezone) {
351 $a_timezone = $this->getTimeZoneIdentifier();
352 }
353
354 $date = new DateTime($format, new DateTimeZone($a_timezone));
355 } else {
356 $date = new DateTime($format);
357 }
358 } catch (Exception $ex) {
359 // :TODO: do anything?
360 }
361 return ($date instanceof DateTime)
362 ? $date
363 : null;
364 }
365
371 public function setDate($a_date, int $a_format): void
372 {
373 $this->dt_obj = null;
374
375 if (!$a_date) {
376 return;
377 }
378
379 switch ($a_format) {
380 case IL_CAL_UNIX:
381 try {
382 $this->dt_obj = new DateTime('@' . $a_date);
383 $this->dt_obj->setTimezone(new DateTimeZone($this->getTimeZoneIdentifier()));
384 } catch (Exception $ex) {
385 $message = 'Cannot parse date: ' . $a_date . ' with format ' . $a_format;
386 $this->log->warning($message);
387 throw new ilDateTimeException($message);
388 }
389 break;
390
391 case IL_CAL_DATETIME:
392 $matches = preg_match(
393 '/^(\d{4})-?(\d{2})-?(\d{2})([T\s]?(\d{2}):?(\d{2}):?(\d{2})(\.\d+)?(Z|[\+\-]\d{2}:?\d{2})?)$/i',
394 $a_date,
395 $d_parts
396 );
397 if ($matches < 1) {
398 $this->log->warning('Cannot parse date: ' . $a_date);
399 $this->log->warning(print_r($matches, true));
400 $this->log->logStack(ilLogLevel::WARNING);
401 throw new ilDateTimeException('Cannot parse date: ' . $a_date);
402 }
403
404 $tz_id = (isset($d_parts[9]) && $d_parts[9] === 'Z')
405 ? 'UTC'
406 : $this->getTimeZoneIdentifier();
407 $this->dt_obj = $this->parsePartsToDate(
408 (int) $d_parts[1],
409 (int) $d_parts[2],
410 (int) $d_parts[3],
411 (int) $d_parts[5],
412 (int) $d_parts[6],
413 (int) $d_parts[7],
414 $tz_id
415 );
416 break;
417
418 case IL_CAL_DATE:
419 try {
420 // Pure dates are not timezone sensible.
421 $this->dt_obj = new DateTime($a_date, new DateTimeZone('UTC'));
422 } catch (Exception $ex) {
423 $this->log->warning('Cannot parse date : ' . $a_date);
424 throw new ilDateTimeException('Cannot parse date: ' . $a_date);
425 }
426 break;
427
429 // Format like getdate parameters
430 $this->dt_obj = $this->parsePartsToDate(
431 (int) $a_date['year'],
432 (int) $a_date['mon'],
433 (int) $a_date['mday'],
434 (int) $a_date['hours'],
435 (int) $a_date['minutes'],
436 (int) ($a_date['seconds'] ?? 0),
437 $this->getTimeZoneIdentifier()
438 );
439 break;
440
441 case IL_CAL_TIMESTAMP:
442 if (!preg_match("/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/", $a_date, $d_parts)) {
443 $this->log->warning('Cannot parse date: ' . $a_date);
444 throw new ilDateTimeException('Cannot parse date.');
445 }
446 $this->dt_obj = $this->parsePartsToDate(
447 (int) $d_parts[1],
448 (int) $d_parts[2],
449 (int) $d_parts[3],
450 (int) $d_parts[4],
451 (int) $d_parts[5],
452 (int) $d_parts[6],
453 $this->getTimeZoneIdentifier()
454 );
455 break;
456
457 case IL_CAL_ISO_8601:
462 $this->dt_obj = DateTime::createFromFormat(
463 DateTime::ATOM,
464 $a_date,
465 new DateTimeZone($this->getTimeZoneIdentifier())
466 );
467 break;
468 }
469 // remove set timezone since it does not influence the internal date.
470 // the tz must be passed in the moment of the creation of the date object.
471 }
472
477 public function get(int $a_format, string $a_format_str = '', string $a_tz = '')
478 {
479 if ($this->isNull()) {
480 return null;
481 }
482
483 $timezone = $this->default_timezone;
484 if ($a_tz) {
485 try {
486 $timezone = ilTimeZone::_getInstance($a_tz);
487 } catch (ilTimeZoneException $exc) {
488 $this->log->warning('Invalid timezone given. Timezone: ' . $a_tz);
489 }
490 }
491 $out_date = clone($this->dt_obj);
492 $out_date->setTimezone(new DateTimeZone($timezone->getIdentifier()));
493
494 $date = null;
495 switch ($a_format) {
496 case IL_CAL_UNIX:
497 // timezone unrelated
498 $date = $this->getUnixTime();
499 break;
500
501 case IL_CAL_DATE:
502 $date = $out_date->format('Y-m-d');
503 break;
504
505 case IL_CAL_DATETIME:
506 $date = $out_date->format('Y-m-d H:i:s');
507 break;
508
509 case IL_CAL_FKT_DATE:
510 $date = $out_date->format($a_format_str);
511 break;
512
514 $date = array(
515 'seconds' => (int) $out_date->format('s')
516 ,
517 'minutes' => (int) $out_date->format('i')
518 ,
519 'hours' => (int) $out_date->format('G')
520 ,
521 'mday' => (int) $out_date->format('j')
522 ,
523 'wday' => (int) $out_date->format('w')
524 ,
525 'mon' => (int) $out_date->format('n')
526 ,
527 'year' => (int) $out_date->format('Y')
528 ,
529 'yday' => (int) $out_date->format('z')
530 ,
531 'weekday' => $out_date->format('l')
532 ,
533 'month' => $out_date->format('F')
534 ,
535 'isoday' => (int) $out_date->format('N')
536 );
537 break;
538
539 case IL_CAL_ISO_8601:
540 $date = $out_date->format('c');
541 break;
542
543 case IL_CAL_TIMESTAMP:
544 $date = $out_date->format('YmdHis');
545 break;
546 }
547 return $date;
548 }
549
557 public function __toString(): string
558 {
559 return $this->get(IL_CAL_DATETIME) . '<br>';
560 }
561}
const IL_CAL_FKT_GETDATE
const IL_CAL_DATE
const IL_CAL_WEEK
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_HOUR
const IL_CAL_DAY
const IL_CAL_SECOND
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
@classDescription Date and time handling
parsePartsToDate(int $a_year, int $a_month, int $a_day, ?int $a_hour=null, ?int $a_min=null, ?int $a_sec=null, ?string $a_timezone=null)
setDate($a_date, int $a_format)
Set date.
isNull()
Check if a date is null (Datetime == '0000-00-00 00:00:00', unixtime == 0,...)
__construct($a_date=null, int $a_format=0, string $a_tz='')
Create new date object.
static _after(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
compare two dates and check start is after end This method does not consider tz offsets.
DateTime $dt_obj
static _within(ilDateTime $dt, ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
Check whether an date is within a date duration given by start and end.
static _equals(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
Check if two date are equal.
__toString()
to string for date time objects Output is user time zone @access public
ilTimeZone $timezone
switchTimeZone(string $a_timezone_identifier='')
Switch timezone.
increment(string $a_type, int $a_count=1)
ilTimeZone $default_timezone
static _before(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
compare two dates and check start is before end This method does not consider tz offsets.
Component logger with individual log levels by component id.
Class for TimeZone exceptions.
This class offers methods for timezone handling.
static _getInstance(string $a_tz='')
get instance by timezone
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26
$message
Definition: xapiexit.php:31