ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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 
5 include_once('Services/Calendar/classes/class.ilDateTimeException.php');
6 include_once('Services/Calendar/classes/class.ilTimeZone.php');
7 
8 
9 define('IL_CAL_DATETIME', 1);
10 define('IL_CAL_DATE', 2);
11 define('IL_CAL_UNIX', 3);
12 define('IL_CAL_FKT_DATE', 4);
13 define('IL_CAL_FKT_GETDATE', 5);
14 define('IL_CAL_TIMESTAMP', 6);
15 define('IL_CAL_ISO_8601', 7);
16 
17 define('IL_CAL_YEAR', 'year');
18 define('IL_CAL_MONTH', 'month');
19 define('IL_CAL_WEEK', 'week');
20 define('IL_CAL_DAY', 'day');
21 define('IL_CAL_HOUR', 'hour');
22 define('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 
454  case IL_CAL_FKT_GETDATE:
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 
543  case IL_CAL_FKT_GETDATE:
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 }
$format
Definition: metadata.php:141
__construct($a_date=null, $a_format=0, $a_tz='')
Create new date object.
const IL_CAL_DATETIME
global $DIC
Definition: saml.php:7
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.
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.
switchTimeZone($a_timezone_identifier='')
Switch timezone.
const IL_CAL_MONTH
Class for DateTime exceptions.
const IL_CAL_UNIX
__toString()
to string for date time objects Output is user time zone
$start
Definition: bench.php:8
$a_type
Definition: workflow.php:92
const IL_CAL_DAY
getTimeZoneIdentifier()
get timezone identifier
static _equals(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
Check if two date are equal.
catch(Exception $e) $message
getUTCOffset()
get UTC offset
Class for TimeZone exceptions.
const IL_CAL_FKT_DATE
const IL_CAL_ISO_8601
Date and time handling
get($a_format, $a_format_str='', $a_tz='')
get formatted date
increment($a_type, $a_count=1)
increment
const IL_CAL_FKT_GETDATE
static _getInstance($a_tz='')
get instance by timezone
getUnixTime()
get unix time
const IL_CAL_DATE
setDate($a_date, $a_format)
Set date.
parsePartsToDate($a_year, $a_month, $a_day, $a_hour=null, $a_min=null, $a_sec=null, $a_timezone=null)
const IL_CAL_TIMESTAMP
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.
isNull()
Check if a date is null (Datetime == &#39;0000-00-00 00:00:00&#39;, unixtime == 0,...)
const IL_CAL_YEAR