ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
DateTimeParser.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Sabre\VObject;
4 
5 use DateInterval;
7 use DateTimeZone;
8 
20 
34  static function parseDateTime($dt, DateTimeZone $tz = null) {
35 
36  // Format is YYYYMMDD + "T" + hhmmss
37  $result = preg_match('/^([0-9]{4})([0-1][0-9])([0-3][0-9])T([0-2][0-9])([0-5][0-9])([0-5][0-9])([Z]?)$/', $dt, $matches);
38 
39  if (!$result) {
40  throw new InvalidDataException('The supplied iCalendar datetime value is incorrect: ' . $dt);
41  }
42 
43  if ($matches[7] === 'Z' || is_null($tz)) {
44  $tz = new DateTimeZone('UTC');
45  }
46 
47  try {
48  $date = new DateTimeImmutable($matches[1] . '-' . $matches[2] . '-' . $matches[3] . ' ' . $matches[4] . ':' . $matches[5] . ':' . $matches[6], $tz);
49  } catch (\Exception $e) {
50  throw new InvalidDataException('The supplied iCalendar datetime value is incorrect: ' . $dt);
51  }
52 
53  return $date;
54 
55  }
56 
65  static function parseDate($date, DateTimeZone $tz = null) {
66 
67  // Format is YYYYMMDD
68  $result = preg_match('/^([0-9]{4})([0-1][0-9])([0-3][0-9])$/', $date, $matches);
69 
70  if (!$result) {
71  throw new InvalidDataException('The supplied iCalendar date value is incorrect: ' . $date);
72  }
73 
74  if (is_null($tz)) {
75  $tz = new DateTimeZone('UTC');
76  }
77 
78  try {
79  $date = new DateTimeImmutable($matches[1] . '-' . $matches[2] . '-' . $matches[3], $tz);
80  } catch (\Exception $e) {
81  throw new InvalidDataException('The supplied iCalendar date value is incorrect: ' . $date);
82  }
83 
84  return $date;
85 
86  }
87 
99  static function parseDuration($duration, $asString = false) {
100 
101  $result = preg_match('/^(?<plusminus>\+|-)?P((?<week>\d+)W)?((?<day>\d+)D)?(T((?<hour>\d+)H)?((?<minute>\d+)M)?((?<second>\d+)S)?)?$/', $duration, $matches);
102  if (!$result) {
103  throw new InvalidDataException('The supplied iCalendar duration value is incorrect: ' . $duration);
104  }
105 
106  if (!$asString) {
107 
108  $invert = false;
109 
110  if ($matches['plusminus'] === '-') {
111  $invert = true;
112  }
113 
114  $parts = [
115  'week',
116  'day',
117  'hour',
118  'minute',
119  'second',
120  ];
121 
122  foreach ($parts as $part) {
123  $matches[$part] = isset($matches[$part]) && $matches[$part] ? (int)$matches[$part] : 0;
124  }
125 
126  // We need to re-construct the $duration string, because weeks and
127  // days are not supported by DateInterval in the same string.
128  $duration = 'P';
129  $days = $matches['day'];
130 
131  if ($matches['week']) {
132  $days += $matches['week'] * 7;
133  }
134 
135  if ($days) {
136  $duration .= $days . 'D';
137  }
138 
139  if ($matches['minute'] || $matches['second'] || $matches['hour']) {
140 
141  $duration .= 'T';
142 
143  if ($matches['hour']) {
144  $duration .= $matches['hour'] . 'H';
145  }
146 
147  if ($matches['minute']) {
148  $duration .= $matches['minute'] . 'M';
149  }
150 
151  if ($matches['second']) {
152  $duration .= $matches['second'] . 'S';
153  }
154 
155  }
156 
157  if ($duration === 'P') {
158  $duration = 'PT0S';
159  }
160 
161  $iv = new DateInterval($duration);
162 
163  if ($invert) {
164  $iv->invert = true;
165  }
166 
167  return $iv;
168 
169  }
170 
171  $parts = [
172  'week',
173  'day',
174  'hour',
175  'minute',
176  'second',
177  ];
178 
179  $newDur = '';
180 
181  foreach ($parts as $part) {
182  if (isset($matches[$part]) && $matches[$part]) {
183  $newDur .= ' ' . $matches[$part] . ' ' . $part . 's';
184  }
185  }
186 
187  $newDur = ($matches['plusminus'] === '-' ? '-' : '+') . trim($newDur);
188 
189  if ($newDur === '+') {
190  $newDur = '+0 seconds';
191  };
192 
193  return $newDur;
194 
195  }
196 
205  static function parse($date, $referenceTz = null) {
206 
207  if ($date[0] === 'P' || ($date[0] === '-' && $date[1] === 'P')) {
208  return self::parseDuration($date);
209  } elseif (strlen($date) === 8) {
210  return self::parseDate($date, $referenceTz);
211  } else {
212  return self::parseDateTime($date, $referenceTz);
213  }
214 
215  }
216 
273  static function parseVCardDateTime($date) {
274 
275  $regex = '/^
276  (?: # date part
277  (?:
278  (?: (?<year> [0-9]{4}) (?: -)?| --)
279  (?<month> [0-9]{2})?
280  |---)
281  (?<date> [0-9]{2})?
282  )?
283  (?:T # time part
284  (?<hour> [0-9]{2} | -)
285  (?<minute> [0-9]{2} | -)?
286  (?<second> [0-9]{2})?
287 
288  (?: \.[0-9]{3})? # milliseconds
289  (?P<timezone> # timezone offset
290 
291  Z | (?: \+|-)(?: [0-9]{4})
292 
293  )?
294 
295  )?
296  $/x';
297 
298  if (!preg_match($regex, $date, $matches)) {
299 
300  // Attempting to parse the extended format.
301  $regex = '/^
302  (?: # date part
303  (?: (?<year> [0-9]{4}) - | -- )
304  (?<month> [0-9]{2}) -
305  (?<date> [0-9]{2})
306  )?
307  (?:T # time part
308 
309  (?: (?<hour> [0-9]{2}) : | -)
310  (?: (?<minute> [0-9]{2}) : | -)?
311  (?<second> [0-9]{2})?
312 
313  (?: \.[0-9]{3})? # milliseconds
314  (?P<timezone> # timezone offset
315 
316  Z | (?: \+|-)(?: [0-9]{2}:[0-9]{2})
317 
318  )?
319 
320  )?
321  $/x';
322 
323  if (!preg_match($regex, $date, $matches)) {
324  throw new InvalidDataException('Invalid vCard date-time string: ' . $date);
325  }
326 
327  }
328  $parts = [
329  'year',
330  'month',
331  'date',
332  'hour',
333  'minute',
334  'second',
335  'timezone'
336  ];
337 
338  $result = [];
339  foreach ($parts as $part) {
340 
341  if (empty($matches[$part])) {
342  $result[$part] = null;
343  } elseif ($matches[$part] === '-' || $matches[$part] === '--') {
344  $result[$part] = null;
345  } else {
346  $result[$part] = $matches[$part];
347  }
348 
349  }
350 
351  return $result;
352 
353  }
354 
397  static function parseVCardTime($date) {
398 
399  $regex = '/^
400  (?<hour> [0-9]{2} | -)
401  (?<minute> [0-9]{2} | -)?
402  (?<second> [0-9]{2})?
403 
404  (?: \.[0-9]{3})? # milliseconds
405  (?P<timezone> # timezone offset
406 
407  Z | (?: \+|-)(?: [0-9]{4})
408 
409  )?
410  $/x';
411 
412 
413  if (!preg_match($regex, $date, $matches)) {
414 
415  // Attempting to parse the extended format.
416  $regex = '/^
417  (?: (?<hour> [0-9]{2}) : | -)
418  (?: (?<minute> [0-9]{2}) : | -)?
419  (?<second> [0-9]{2})?
420 
421  (?: \.[0-9]{3})? # milliseconds
422  (?P<timezone> # timezone offset
423 
424  Z | (?: \+|-)(?: [0-9]{2}:[0-9]{2})
425 
426  )?
427  $/x';
428 
429  if (!preg_match($regex, $date, $matches)) {
430  throw new InvalidDataException('Invalid vCard time string: ' . $date);
431  }
432 
433  }
434  $parts = [
435  'hour',
436  'minute',
437  'second',
438  'timezone'
439  ];
440 
441  $result = [];
442  foreach ($parts as $part) {
443 
444  if (empty($matches[$part])) {
445  $result[$part] = null;
446  } elseif ($matches[$part] === '-') {
447  $result[$part] = null;
448  } else {
449  $result[$part] = $matches[$part];
450  }
451 
452  }
453 
454  return $result;
455 
456  }
457 
509  static function parseVCardDateAndOrTime($date) {
510 
511  // \d{8}|\d{4}-\d\d|--\d\d(\d\d)?|---\d\d
512  $valueDate = '/^(?J)(?:' .
513  '(?<year>\d{4})(?<month>\d\d)(?<date>\d\d)' .
514  '|(?<year>\d{4})-(?<month>\d\d)' .
515  '|--(?<month>\d\d)(?<date>\d\d)?' .
516  '|---(?<date>\d\d)' .
517  ')$/';
518 
519  // (\d\d(\d\d(\d\d)?)?|-\d\d(\d\d)?|--\d\d)(Z|[+\-]\d\d(\d\d)?)?
520  $valueTime = '/^(?J)(?:' .
521  '((?<hour>\d\d)((?<minute>\d\d)(?<second>\d\d)?)?' .
522  '|-(?<minute>\d\d)(?<second>\d\d)?' .
523  '|--(?<second>\d\d))' .
524  '(?<timezone>(Z|[+\-]\d\d(\d\d)?))?' .
525  ')$/';
526 
527  // (\d{8}|--\d{4}|---\d\d)T\d\d(\d\d(\d\d)?)?(Z|[+\-]\d\d(\d\d?)?
528  $valueDateTime = '/^(?:' .
529  '((?<year0>\d{4})(?<month0>\d\d)(?<date0>\d\d)' .
530  '|--(?<month1>\d\d)(?<date1>\d\d)' .
531  '|---(?<date2>\d\d))' .
532  'T' .
533  '(?<hour>\d\d)((?<minute>\d\d)(?<second>\d\d)?)?' .
534  '(?<timezone>(Z|[+\-]\d\d(\d\d?)))?' .
535  ')$/';
536 
537  // date-and-or-time is date | date-time | time
538  // in this strict order.
539 
540  if (0 === preg_match($valueDate, $date, $matches)
541  && 0 === preg_match($valueDateTime, $date, $matches)
542  && 0 === preg_match($valueTime, $date, $matches)) {
543  throw new InvalidDataException('Invalid vCard date-time string: ' . $date);
544  }
545 
546  $parts = [
547  'year' => null,
548  'month' => null,
549  'date' => null,
550  'hour' => null,
551  'minute' => null,
552  'second' => null,
553  'timezone' => null
554  ];
555 
556  // The $valueDateTime expression has a bug with (?J) so we simulate it.
557  $parts['date0'] = &$parts['date'];
558  $parts['date1'] = &$parts['date'];
559  $parts['date2'] = &$parts['date'];
560  $parts['month0'] = &$parts['month'];
561  $parts['month1'] = &$parts['month'];
562  $parts['year0'] = &$parts['year'];
563 
564  foreach ($parts as $part => &$value) {
565  if (!empty($matches[$part])) {
566  $value = $matches[$part];
567  }
568  }
569 
570  unset($parts['date0']);
571  unset($parts['date1']);
572  unset($parts['date2']);
573  unset($parts['month0']);
574  unset($parts['month1']);
575  unset($parts['year0']);
576 
577  return $parts;
578 
579  }
580 }
static parse($date, $referenceTz=null)
Parses either a Date or DateTime, or Duration value.
static parseVCardTime($date)
This method parses a vCard TIME value.
$result
static parseDateTime($dt, DateTimeZone $tz=null)
Parses an iCalendar (rfc5545) formatted datetime and returns a DateTimeImmutable object.
static parseVCardDateAndOrTime($date)
This method parses a vCard date and or time value.
parseDate($dateString)
A collection of useful helpers for parsing or generating various HTTP headers.
Definition: functions.php:32
static parseDate($date, DateTimeZone $tz=null)
Parses an iCalendar (rfc5545) formatted date and returns a DateTimeImmutable object.
static parseDuration($duration, $asString=false)
Parses an iCalendar (RFC5545) formatted duration value.
static parseVCardDateTime($date)
This method parses a vCard date and or time value.
This exception is thrown whenever an invalid value is found anywhere in a iCalendar or vCard object...