{"record":{"id":"2516107701e372e8","repo":"phacility/phabricator","slug":"expected-iso8601-datetime-in-the-format-19990105t","errorCode":null,"errorMessage":"Expected ISO8601 datetime in the format \"19990105T112233Z\", found \"%s\".","messagePattern":"Expected ISO8601 datetime in the format \"19990105T112233Z\", found \"(.+?)\"\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/calendar/parser/data/PhutilCalendarAbsoluteDateTime.php","lineNumber":26,"sourceCode":"  private $day;\n  private $hour = 0;\n  private $minute = 0;\n  private $second = 0;\n  private $timezone;\n\n  public static function newFromISO8601($value, $timezone = 'UTC') {\n    $pattern =\n      '/^'.\n      '(?P<y>\\d{4})(?P<m>\\d{2})(?P<d>\\d{2})'.\n      '(?:'.\n        'T(?P<h>\\d{2})(?P<i>\\d{2})(?P<s>\\d{2})(?<z>Z)?'.\n      ')?'.\n      '\\z/';\n\n    $matches = null;\n    $ok = preg_match($pattern, $value, $matches);\n    if (!$ok) {\n      throw new Exception(\n        pht(\n          'Expected ISO8601 datetime in the format \"19990105T112233Z\", '.\n          'found \"%s\".',\n          $value));\n    }\n\n    if (isset($matches['z'])) {\n      if ($timezone != 'UTC') {\n        throw new Exception(\n          pht(\n            'ISO8601 date ends in \"Z\" indicating UTC, but a timezone other '.\n            'than UTC (\"%s\") was specified.',\n            $timezone));\n      }\n    }\n\n    $datetime = id(new self())\n      ->setYear((int)$matches['y'])","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/calendar/parser/data/PhutilCalendarAbsoluteDateTime.php#L8-L44","documentation":"PhutilCalendarAbsoluteDateTime::newFromISO8601() accepts only the basic ISO 8601 form YYYYMMDD, optionally followed by THHMMSS and an optional trailing Z. Any deviation - hyphens, colons, timezone offsets like +0100, missing digits, or an empty string - fails the regex and throws.","triggerScenarios":"newFromISO8601('2024-01-05'), newFromISO8601('20240105T11:22:33'), newFromISO8601('20240105T112233+0100'), newFromISO8601(''). Extended-format values from PHP's DateTime::format('c') or from ICS files with relaxed producers.","commonSituations":"Passing output of date('c') or DATE_ATOM; user-typed dates; third-party ICS/calendar feeds emitting extended ISO format; whitespace padding around the value.","solutions":["Normalize to basic format before parsing: strip everything except digits and a trailing Z (e.g. preg_replace('/[^0-9TZ]/', '', $value)).","Generate correct values directly: gmdate('Ymd\\\\THis\\\\Z', $timestamp).","If the input carries an offset, convert it to a UTC timestamp first (new DateTime($input)->getTimestamp()) and format as basic UTC.","Trim whitespace: $value = trim($value) before calling."],"exampleFix":"// before\n$dt = PhutilCalendarAbsoluteDateTime::newFromISO8601('2024-01-05T11:22:33Z');\n// after\n$dt = PhutilCalendarAbsoluteDateTime::newFromISO8601('20240105T112233Z');","handlingStrategy":"type-guard","validationCode":"$value = trim($value);\nif (!preg_match('/^\\d{4}\\d{2}\\d{2}(T\\d{2}\\d{2}\\d{2}Z?)?$/', $value)) {\n  // normalize extended format to basic before calling the parser\n  $dt = new DateTime($value);\n  $value = $dt->format('Ymd\\\\THis');\n}\n$abs = PhutilCalendarAbsoluteDateTime::newFromISO8601($value);","typeGuard":"function isBasicIso8601DateTime($value) {\n  return (bool) preg_match('/^\\d{4}\\d{2}\\d{2}(T\\d{2}\\d{2}\\d{2}Z?)?$/', trim((string)$value));\n}","tryCatchPattern":"try {\n  $dt = PhutilCalendarAbsoluteDateTime::newFromISO8601($value, $tz);\n} catch (Exception $ex) {\n  // skip/log the bad property; keep parsing the rest of the ICS object\n  phlog('Bad ISO8601 datetime: '.$value);\n  continue;\n}","preventionTips":["Generate values with gmdate('Ymd\\\\THis\\\\Z', $ts) instead of date('c').","Strip separators when importing: preg_replace('/[^0-9TZ]/', '', $value).","Trim whitespace on all externally sourced datetime strings."],"tags":["phutil","calendar","iso8601","datetime","parse-error"],"backgroundTag":"datetime-parse-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}