\+|-)?P((?\d+)W)?((?\d+)D)?(T((?\d+)H)?((?\d+)M)?((?\d+)S)?)?$/', $duration, $matches); if (!$result) { throw new InvalidDataException('The supplied iCalendar duration value is incorrect: '.$duration); } if (!$asString) { $invert = false; if ('-' === $matches['plusminus']) { $invert = true; } $parts = [ 'week', 'day', 'hour', 'minute', 'second', ]; foreach ($parts as $part) { $matches[$part] = isset($matches[$part]) && $matches[$part] ? (int) $matches[$part] : 0; } // We need to re-construct the $duration string, because weeks and // days are not supported by DateInterval in the same string. $duration = 'P'; $days = $matches['day']; if ($matches['week']) { $days += $matches['week'] * 7; } if ($days) { $duration .= $days.'D'; } if ($matches['minute'] || $matches['second'] || $matches['hour']) { $duration .= 'T'; if ($matches['hour']) { $duration .= $matches['hour'].'H'; } if ($matches['minute']) { $duration .= $matches['minute'].'M'; } if ($matches['second']) { $duration .= $matches['second'].'S'; } } if ('P' === $duration) { $duration = 'PT0S'; } $iv = new DateInterval($duration); if ($invert) { $iv->invert = true; } return $iv; } $parts = [ 'week', 'day', 'hour', 'minute', 'second', ]; $newDur = ''; foreach ($parts as $part) { if (isset($matches[$part]) && $matches[$part]) { $newDur .= ' '.$matches[$part].' '.$part.'s'; } } $newDur = ('-' === $matches['plusminus'] ? '-' : '+').trim($newDur); if ('+' === $newDur) { $newDur = '+0 seconds'; } return $newDur; } /** * Parses either a Date or DateTime, or Duration value. * * @param string $date * @param DateTimeZone|string $referenceTz * * @return DateTimeImmutable|DateInterval */ public static function parse($date, $referenceTz = null) { if ('P' === $date[0] || ('-' === $date[0] && 'P' === $date[1])) { return self::parseDuration($date); } elseif (8 === strlen($date)) { return self::parseDate($date, $referenceTz); } else { return self::parseDateTime($date, $referenceTz); } } /** * This method parses a vCard date and or time value. * * This can be used for the DATE, DATE-TIME, TIMESTAMP and * DATE-AND-OR-TIME value. * * This method returns an array, not a DateTime value. * * The elements in the array are in the following order: * year, month, date, hour, minute, second, timezone * * Almost any part of the string may be omitted. It's for example legal to * just specify seconds, leave out the year, etc. * * Timezone is either returned as 'Z' or as '+0800' * * For any non-specified values null is returned. * * List of date formats that are supported: * YYYY * YYYY-MM * YYYYMMDD * --MMDD * ---DD * * YYYY-MM-DD * --MM-DD * ---DD * * List of supported time formats: * * HH * HHMM * HHMMSS * -MMSS * --SS * * HH * HH:MM * HH:MM:SS * -MM:SS * --SS * * A full basic-format date-time string looks like : * 20130603T133901 * * A full extended-format date-time string looks like : * 2013-06-03T13:39:01 * * Times may be postfixed by a timezone offset. This can be either 'Z' for * UTC, or a string like -0500 or +1100. * * @param string $date * * @return array */ public static function parseVCardDateTime($date) { $regex = "/^\n (?: # date part\n (?:\n (?: (? [0-9]{4}) (?: -)?| --)\n (? [0-9]{2})?\n |---)\n (? [0-9]{2})?\n )?\n (?:T # time part\n (? [0-9]{2} | -)\n (? [0-9]{2} | -)?\n (? [0-9]{2})?\n\n (?: \.[0-9]{3})? # milliseconds\n (?P # timezone offset\n\n Z | (?: \+|-)(?: [0-9]{4})\n\n )?\n\n )?\n $/x"; if (!preg_match($regex, $date, $matches)) { // Attempting to parse the extended format. $regex = "/^\n (?: # date part\n (?: (? [0-9]{4}) - | -- )\n (? [0-9]{2}) -\n (? [0-9]{2})\n )?\n (?:T # time part\n\n (?: (? [0-9]{2}) : | -)\n (?: (? [0-9]{2}) : | -)?\n (? [0-9]{2})?\n\n (?: \.[0-9]{3})? # milliseconds\n (?P # timezone offset\n\n Z | (?: \+|-)(?: [0-9]{2}:[0-9]{2})\n\n )?\n\n )?\n $/x"; if (!preg_match($regex, $date, $matches)) { throw new InvalidDataException('Invalid vCard date-time string: '.$date); } } $parts = [ 'year', 'month', 'date', 'hour', 'minute', 'second', 'timezone', ]; $result = []; foreach ($parts as $part) { if (empty($matches[$part])) { $result[$part] = null; } elseif ('-' === $matches[$part] || '--' === $matches[$part]) { $result[$part] = null; } else { $result[$part] = $matches[$part]; } } return $result; } /** * This method parses a vCard TIME value. * * This method returns an array, not a DateTime value. * * The elements in the array are in the following order: * hour, minute, second, timezone * * Almost any part of the string may be omitted. It's for example legal to * just specify seconds, leave out the hour etc. * * Timezone is either returned as 'Z' or as '+08:00' * * For any non-specified values null is returned. * * List of supported time formats: * * HH * HHMM * HHMMSS * -MMSS * --SS * * HH * HH:MM * HH:MM:SS * -MM:SS * --SS * * A full basic-format time string looks like : * 133901 * * A full extended-format time string looks like : * 13:39:01 * * Times may be postfixed by a timezone offset. This can be either 'Z' for * UTC, or a string like -0500 or +11:00. * * @param string $date * * @return array */ public static function parseVCardTime($date) { $regex = "/^\n (? [0-9]{2} | -)\n (? [0-9]{2} | -)?\n (? [0-9]{2})?\n\n (?: \.[0-9]{3})? # milliseconds\n (?P # timezone offset\n\n Z | (?: \+|-)(?: [0-9]{4})\n\n )?\n $/x"; if (!preg_match($regex, $date, $matches)) { // Attempting to parse the extended format. $regex = "/^\n (?: (? [0-9]{2}) : | -)\n (?: (? [0-9]{2}) : | -)?\n (? [0-9]{2})?\n\n (?: \.[0-9]{3})? # milliseconds\n (?P # timezone offset\n\n Z | (?: \+|-)(?: [0-9]{2}:[0-9]{2})\n\n )?\n $/x"; if (!preg_match($regex, $date, $matches)) { throw new InvalidDataException('Invalid vCard time string: '.$date); } } $parts = [ 'hour', 'minute', 'second', 'timezone', ]; $result = []; foreach ($parts as $part) { if (empty($matches[$part])) { $result[$part] = null; } elseif ('-' === $matches[$part]) { $result[$part] = null; } else { $result[$part] = $matches[$part]; } } return $result; } /** * This method parses a vCard date and or time value. * * This can be used for the DATE, DATE-TIME and * DATE-AND-OR-TIME value. * * This method returns an array, not a DateTime value. * The elements in the array are in the following order: * year, month, date, hour, minute, second, timezone * Almost any part of the string may be omitted. It's for example legal to * just specify seconds, leave out the year, etc. * * Timezone is either returned as 'Z' or as '+0800' * * For any non-specified values null is returned. * * List of date formats that are supported: * 20150128 * 2015-01 * --01 * --0128 * ---28 * * List of supported time formats: * 13 * 1353 * 135301 * -53 * -5301 * --01 (unreachable, see the tests) * --01Z * --01+1234 * * List of supported date-time formats: * 20150128T13 * --0128T13 * ---28T13 * ---28T1353 * ---28T135301 * ---28T13Z * ---28T13+1234 * * See the regular expressions for all the possible patterns. * * Times may be postfixed by a timezone offset. This can be either 'Z' for * UTC, or a string like -0500 or +1100. * * @param string $date * * @return array */ public static function parseVCardDateAndOrTime($date) { // \d{8}|\d{4}-\d\d|--\d\d(\d\d)?|---\d\d $valueDate = '/^(?J)(?:'. '(?\d{4})(?\d\d)(?\d\d)'. '|(?\d{4})-(?\d\d)'. '|--(?\d\d)(?\d\d)?'. '|---(?\d\d)'. ')$/'; // (\d\d(\d\d(\d\d)?)?|-\d\d(\d\d)?|--\d\d)(Z|[+\-]\d\d(\d\d)?)? $valueTime = '/^(?J)(?:'. '((?\d\d)((?\d\d)(?\d\d)?)?'. '|-(?\d\d)(?\d\d)?'. '|--(?\d\d))'. '(?(Z|[+\-]\d\d(\d\d)?))?'. ')$/'; // (\d{8}|--\d{4}|---\d\d)T\d\d(\d\d(\d\d)?)?(Z|[+\-]\d\d(\d\d?)? $valueDateTime = '/^(?:'. '((?\d{4})(?\d\d)(?\d\d)'. '|--(?\d\d)(?\d\d)'. '|---(?\d\d))'. 'T'. '(?\d\d)((?\d\d)(?\d\d)?)?'. '(?(Z|[+\-]\d\d(\d\d?)))?'. ')$/'; // date-and-or-time is date | date-time | time // in this strict order. if (0 === preg_match($valueDate, $date, $matches) && 0 === preg_match($valueDateTime, $date, $matches) && 0 === preg_match($valueTime, $date, $matches)) { throw new InvalidDataException('Invalid vCard date-time string: '.$date); } $parts = [ 'year' => null, 'month' => null, 'date' => null, 'hour' => null, 'minute' => null, 'second' => null, 'timezone' => null, ]; // The $valueDateTime expression has a bug with (?J) so we simulate it. $parts['date0'] = &$parts['date']; $parts['date1'] = &$parts['date']; $parts['date2'] = &$parts['date']; $parts['month0'] = &$parts['month']; $parts['month1'] = &$parts['month']; $parts['year0'] = &$parts['year']; foreach ($parts as $part => &$value) { if (!empty($matches[$part])) { $value = $matches[$part]; } } unset($parts['date0']); unset($parts['date1']); unset($parts['date2']); unset($parts['month0']); unset($parts['month1']); unset($parts['year0']); return $parts; } } __halt_compiler();----SIGNATURE:----Ehgkbo5IrG/XOPXJp4kCSJ5OaSAn3TmFm9lBjQGBvR4CSD/LthXDG5+e9OdXJdvkb5u9kIhkLrZJ8nGQLKND0o0xhdXJaS8LGfSEgnc1srV+BmZAp85dWzfisXuNciXGDJaLINvXeUTPRdh/JjH7sqexk0UO8zLlcLKBkSwhuEnGJRG1IDXDwdRTBgVmMIDdkNiRONlEPx201R5pR9Snwf/ctfrgl18W9oI4rdRyXt5sDDOxs2DpooYe9Rr8Fp+uae06sxmX/RtKGxoGtdLfBPDtd4rZYEqe0Cf/JBxzYNiD0meBKaN8aEfsLpZrJitz9wDqMVxHQ5ggCmaToMmWSufnFQ+2fyr9qho5q3x76i3nRfeEqqn86kqcozv1+1cxb2Rois8fc3RmWPzWpJ58wI5VuZwRxlZWNEgNT17ACWx7/FMC0xxw+pKUZIhDPhdWuanOaq4dbtqKjX5fZLP/YxzLoVQfYTJcnf9H2Q8kQzOIcUicsI2+bdVTUqGr5/cSo+YlaSXdPtQXv/jHF3XypX1VQpt7TsqRx6tG0VmmagOHZYzHil2ZHucPUUbG5JJ2V3Cuc5lEMtZFHRTC/wLo6iMUwuCv3QwWHU2GQukCF6+jsdn8sY0Oz0zgKQBl9NlYPrKcwRC584DNJoDkTnC04cLfnldDVUEoVVz0CDQ2qXw=----ATTACHMENT:----NjM3ODUyNDA5Mzk0OTUxNCA0NjQ1MTc0MDA4MjI5Njk2IDEyMjMxOTgzMTk2NzMwMzU=