Php datetime createfromformat iso 8601

Nobody mentioned to use DATE_ATOM which is as far as i know phps most correct implementation of ISO 8601. It should at least work for the last 3 of these:

format(DATE_ATOM)
);

foreach($dates as $d) {

    $res = \DateTime::createFromFormat(DATE_ATOM, $d);

    echo "try $d: \n";
    var_dump($res);
    echo "\n\n";
}

?>

To be able to parse all of them i wrote a tiny function:

 0) {
        return $success[0];
    }
    return false;
}

// Test
$dates = array(
    "2010-12-07T23:00:00.000Z",
    "2010-12-07T23:00:00",
    "2010-12-07T23:00:00Z",
    "2010-12-07T23:00:00+01:00",
    (new \DateTime("now"))->format(DATE_ATOM)
);

foreach($dates as $d) {

    $res = parse_iso_8601($d);

    echo "try $d: \n";
    var_dump($res);
    echo "\n\n";
}

?>

As @Glutexo mentioned it works only if there are only 1 to 6 precision digits for the decimal part, too. Feel free to improve it.

PHP DateTime class – parsing and formatting ISO8601 dates with or w/o fractions of a second

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

echo 'default locale: ' . \Locale::getDefault();
echo PHP_EOL;
echo 'default timezone: ' . \date_default_timezone_get();
echo PHP_EOL;
// see http://tools.ietf.org/html/rfc3339#section-5.8 for example datetimes
// bug report on missing fractions support: https://bugs.php.net/bug.php?id=51950
// feature request for fractions support in constructor: https://bugs.php.net/bug.php?id=49779
$dt2 = \DateTime::createFromFormat('Y-m-d\TH:m:i.uO', '2012-10-17');
var_dump($dt2); // false
$dt2 = new \DateTime('2012-10-17');
echo '2012-10-17 formatted => ' . $dt2->format('Y-m-d\TH:i:s.uP');
echo PHP_EOL;
$dt3 = \DateTime::createFromFormat('Y-m-d\TH:m:i.uO', '1990-12-31T23:59:60Z'); // leap second
var_dump($dt3); // false
$dt3 = new \DateTime('1990-12-31T23:59:60Z');
echo '1990-12-31T23:59:60Z formatted => ' . $dt3->format('Y-m-d\TH:i:s.uP');
echo PHP_EOL;
$dt4 = \DateTime::createFromFormat(\DateTime::ISO8601, '2004-02-13T15:19:21+00:00');
echo '2004-02-13T15:19:21+00:00 formatted => ' . $dt4->format('Y-m-d\TH:i:s.uP');
echo PHP_EOL;
$dt5 = \DateTime::createFromFormat('Y-m-d\TH:m:i.uO', '1985-04-12T23:20:50.52Z');
echo '1985-04-12T23:20:50.52Z formatted => ' . $dt5->format('Y-m-d\TH:i:s.uP');
echo PHP_EOL;
echo '\DateTime::createFromFormat(DateTime::ISO8601, "1985-04-12T23:20:50.52Z") => ';
$datetime = \DateTime::createFromFormat(\DateTime::ISO8601, '1985-04-12T23:20:50.52Z');
var_dump($datetime);
echo 'new \DateTime("1985-04-12T23:20:50.52Z") => ';
$datetime = new \DateTime('1985-04-12T23:20:50.52Z');
var_dump($datetime);
echo '1985-04-12T23:20:50.52Z formatted (P) => ' . $datetime->format('Y-m-d\TH:i:s.uP');
echo PHP_EOL;
//$datetime = \DateTime::createFromFormat('c', '1985-04-12T23:20:50.52Z'); // fails
$datetime = new \DateTime('1985-04-12T23:20:50.52Z');
var_dump($datetime);
$datetimez = clone $datetime;
$datetime->setTimeZone(new \DateTimeZone('Zulu'));
$datetime->setTimeZone(new \DateTimeZone('Etc/UTC'));
$datetime->setTimeZone(new \DateTimeZone('UTC'));
echo '1985-04-12T23:20:50.52Z clone Z formatted => ' . $datetime->format('Y-m-d\TH:i:s.u\Z');
echo PHP_EOL;
echo '1985-04-12T23:20:50.52Z clone Z formatted => ' . $datetime->format('Y-m-d\TH:i:s.uP');
echo PHP_EOL;
$iso8601_p = sprintf(
"%s%03d%s",
$datetime->format("Y-m-d\TH:i:s\."),
floor($datetime->format("u") / 1000),
$datetime->format("P")
);
echo '1985-04-12T23:20:50.52Z clone custom formatted P => ' . $iso8601_p;
echo PHP_EOL;
$iso8601_z = sprintf(
"%s%03dZ",
$datetime->format("Y-m-d\TH:i:s\."),
floor($datetime->format("u") / 1000)
);
echo '1985-04-12T23:20:50.52Z clone custom formatted Z => ' . $iso8601_z;
echo PHP_EOL;
echo '\DateTime::diff() with fractions of a second granularity is not possible…';
echo PHP_EOL;
echo "Propably need to use format('u') and compare those when treated as integer…";
echo PHP_EOL;
echo 'NOW with fractions (P): ' . \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)))->format('Y-m-d\TH:i:s.uP');
echo PHP_EOL;
echo 'NOW with fractions (O): ' . \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)))->format('Y-m-d\TH:i:s.uO');
echo PHP_EOL;