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);
 
   43        if ($matches[7] === 
'Z' || is_null(
$tz)) {
 
   44            $tz = 
new DateTimeZone(
'UTC');
 
   48            $date = 
new DateTimeImmutable($matches[1] . 
'-' . $matches[2] . 
'-' . $matches[3] . 
' ' . $matches[4] . 
':' . $matches[5] . 
':' . $matches[6], 
$tz);
 
   49        } 
catch (\Exception $e) {
 
   68        $result = preg_match(
'/^([0-9]{4})([0-1][0-9])([0-3][0-9])$/', $date, $matches);
 
   75            $tz = 
new DateTimeZone(
'UTC');
 
   79            $date = 
new DateTimeImmutable($matches[1] . 
'-' . $matches[2] . 
'-' . $matches[3], 
$tz);
 
   80        } 
catch (\Exception $e) {
 
  101        $result = preg_match(
'/^(?<plusminus>\+|-)?P((?<week>\d+)W)?((?<day>\d+)D)?(T((?<hour>\d+)H)?((?<minute>\d+)M)?((?<second>\d+)S)?)?$/', $duration, $matches);
 
  103            throw new InvalidDataException(
'The supplied iCalendar duration value is incorrect: ' . $duration);
 
  110            if ($matches[
'plusminus'] === 
'-') {
 
  122            foreach ($parts as $part) {
 
  123                $matches[$part] = isset($matches[$part]) && $matches[$part] ? (int)$matches[$part] : 0;
 
  129            $days = $matches[
'day'];
 
  131            if ($matches[
'week']) {
 
  132                $days += $matches[
'week'] * 7;
 
  136                $duration .= $days . 
'D';
 
  139            if ($matches[
'minute'] || $matches[
'second'] || $matches[
'hour']) {
 
  143                if ($matches[
'hour']) {
 
  144                    $duration .= $matches[
'hour'] . 
'H';
 
  147                if ($matches[
'minute']) {
 
  148                    $duration .= $matches[
'minute'] . 
'M';
 
  151                if ($matches[
'second']) {
 
  152                    $duration .= $matches[
'second'] . 
'S';
 
  157            if ($duration === 
'P') {
 
  161            $iv = 
new DateInterval($duration);
 
  181        foreach ($parts as $part) {
 
  182            if (isset($matches[$part]) && $matches[$part]) {
 
  183                $newDur .= 
' ' . $matches[$part] . 
' ' . $part . 
's';
 
  187        $newDur = ($matches[
'plusminus'] === 
'-' ? 
'-' : 
'+') . trim($newDur);
 
  189        if ($newDur === 
'+') {
 
  190            $newDur = 
'+0 seconds';
 
  205    static function parse($date, $referenceTz = 
null) {
 
  207        if ($date[0] === 
'P' || ($date[0] === 
'-' && $date[1] === 
'P')) {
 
  209        } elseif (strlen($date) === 8) {
 
  278                    (?: (?<year> [0-9]{4}) (?: -)?| --) 
  284                (?<hour> [0-9]{2} | -) 
  285                (?<minute> [0-9]{2} | -)? 
  286                (?<second> [0-9]{2})? 
  288                (?: \.[0-9]{3})? # milliseconds 
  289                (?P<timezone> # timezone offset 
  291                    Z | (?: \+|-)(?: [0-9]{4}) 
  298        if (!preg_match($regex, $date, $matches)) {
 
  303                    (?: (?<year> [0-9]{4}) - | -- ) 
  304                    (?<month> [0-9]{2}) - 
  309                    (?: (?<hour> [0-9]{2}) : | -) 
  310                    (?: (?<minute> [0-9]{2}) : | -)? 
  311                    (?<second> [0-9]{2})? 
  313                    (?: \.[0-9]{3})? # milliseconds 
  314                    (?P<timezone> # timezone offset 
  316                        Z | (?: \+|-)(?: [0-9]{2}:[0-9]{2}) 
  323            if (!preg_match($regex, $date, $matches)) {
 
  339        foreach ($parts as $part) {
 
  341            if (empty($matches[$part])) {
 
  343            } elseif ($matches[$part] === 
'-' || $matches[$part] === 
'--') {
 
  346                $result[$part] = $matches[$part];
 
  400            (?<hour> [0-9]{2} | -) 
  401            (?<minute> [0-9]{2} | -)? 
  402            (?<second> [0-9]{2})? 
  404            (?: \.[0-9]{3})? # milliseconds 
  405            (?P<timezone> # timezone offset 
  407                Z | (?: \+|-)(?: [0-9]{4}) 
  413        if (!preg_match($regex, $date, $matches)) {
 
  417                (?: (?<hour> [0-9]{2}) : | -) 
  418                (?: (?<minute> [0-9]{2}) : | -)? 
  419                (?<second> [0-9]{2})? 
  421                (?: \.[0-9]{3})? # milliseconds 
  422                (?P<timezone> # timezone offset 
  424                    Z | (?: \+|-)(?: [0-9]{2}:[0-9]{2}) 
  429            if (!preg_match($regex, $date, $matches)) {
 
  442        foreach ($parts as $part) {
 
  444            if (empty($matches[$part])) {
 
  446            } elseif ($matches[$part] === 
'-') {
 
  449                $result[$part] = $matches[$part];
 
  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)' .
 
  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)?))?' .
 
  528        $valueDateTime = 
'/^(?:' .
 
  529                         '((?<year0>\d{4})(?<month0>\d\d)(?<date0>\d\d)' .
 
  530                         '|--(?<month1>\d\d)(?<date1>\d\d)' .
 
  531                         '|---(?<date2>\d\d))' .
 
  533                         '(?<hour>\d\d)((?<minute>\d\d)(?<second>\d\d)?)?' .
 
  534                         '(?<timezone>(Z|[+\-]\d\d(\d\d?)))?' .
 
  540        if (0 === preg_match($valueDate, $date, $matches)
 
  541            && 0 === preg_match($valueDateTime, $date, $matches)
 
  542            && 0 === preg_match($valueTime, $date, $matches)) {
 
  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'];
 
  564        foreach ($parts as $part => &$value) {
 
  565            if (!empty($matches[$part])) {
 
  566                $value = $matches[$part];
 
  570        unset($parts[
'date0']);
 
  571        unset($parts[
'date1']);
 
  572        unset($parts[
'date2']);
 
  573        unset($parts[
'month0']);
 
  574        unset($parts[
'month1']);
 
  575        unset($parts[
'year0']);
 
An exception for terminatinating execution or to throw for unit testing.
static parseVCardDateTime($date)
This method parses a vCard date and or time value.
static parseVCardDateAndOrTime($date)
This method parses a vCard date and or time value.
static parse($date, $referenceTz=null)
Parses either a Date or DateTime, or Duration value.
static parseDuration($duration, $asString=false)
Parses an iCalendar (RFC5545) formatted duration value.
static parseDateTime($dt, DateTimeZone $tz=null)
Parses an iCalendar (rfc5545) formatted datetime and returns a DateTimeImmutable object.
static parseVCardTime($date)
This method parses a vCard TIME value.
static parseDate($date, DateTimeZone $tz=null)
Parses an iCalendar (rfc5545) formatted date and returns a DateTimeImmutable object.
This exception is thrown whenever an invalid value is found anywhere in a iCalendar or vCard object.