PHP DateTime :: createFromFormat не обрабатывает дату ISO 8601

Код говорит миллион слов:

php > echo strtotime("2010-12-07T23:00:00.000Z"); 1291762800 echo date('c', 1291762800); 2010-12-08T00:00:00+01:00 php > var_dump(DateTime::createFromFormat('c', "2010-12-07T23:00:00.000Z")); bool(false) php > var_dump(DateTime::createFromFormat(DateTime::ISO8601, "2010-12-07T23:00:00.000Z")); bool(false) 

Любая идея, что происходит?

Btw, да, новый DateTime («2010-12-07T23: 00: 00.000Z») работает нормально. Но я предпочитаю знать, какой вклад я получаю.

Есть отчет об ошибке, который точно описывает вашу проблему 🙂

https://bugs.php.net/bug.php?id=51950

С 2016-08-07 отчет об ошибке был отмечен как «не ошибка». Вместо этого вам нужно использовать strtotime или new DateTime .

Определенные константы применяются как к форматированию, так и к синтаксическому анализу таким же образом, что заставляет ваши пути.

Синхронизация даты ISO8601, а также временная зона переключения:

 // create ISO8601 dateTime $date = DateTime::createFromFormat(DateTime::ISO8601, '2016-07-27T19:30:00Z'); // set to user's timezone $date -> setTimeZone('Asia/Singapore'); echo $date -> format(DateTime::ISO8601); // prints '2016-07-28T03:30:00+0800' 

попробуй это:

 DateTime::createFromFormat('Ymd\TH:i:sP', $date) 

Никто не упомянул использовать DATE_ATOM, насколько я знаю, наиболее правильная реализация ИСО 8601. Он должен по крайней мере работать для последних 3 из них:

 <?php $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 = \DateTime::createFromFormat(DATE_ATOM, $d); echo "try $d: \n"; var_dump($res); echo "\n\n"; } ?> 

Чтобы иметь возможность разбирать все из них, я написал крошечную функцию:

 <?php function parse_iso_8601($iso_8601_string) { $results = array(); $results[] = \DateTime::createFromFormat("Ymd\TH:i:s",$iso_8601_string); $results[] = \DateTime::createFromFormat("Ymd\TH:i:su",$iso_8601_string); $results[] = \DateTime::createFromFormat("Ymd\TH:i:s.uP",$iso_8601_string); $results[] = \DateTime::createFromFormat("Ymd\TH:i:sP",$iso_8601_string); $results[] = \DateTime::createFromFormat(DATE_ATOM,$iso_8601_string); $success = array_values(array_filter($results)); if(count($success) > 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"; } ?> 

Как упоминал @Glutexo, он работает только в том случае, если для десятичной части есть только от 1 до 6 цифр точности. Не стесняйтесь улучшать его.

Очень странно и неутешительно, что эта ошибка по-прежнему актуальна. Вот правильный шаблон для парсинга даты с микросекундами в десятичной части секунд:

 Ymd\TH:i:s.uO 

Применение:

 $dateStr = '2015-04-29T11:42:56.000+0400' $ISO = 'Ymd\TH:i:s.uO' $date = DateTime::createFromFormat($ISO, $dateStr) 

Для ответа, указанного здесь https://stackoverflow.com/a/14849503/2425651, мы можем использовать этот формат «Ymd \ TH: i: s.u +», чтобы сохранить микросекунды.

 $format = 'Ymd\TH:i:s.u+'; $value = '2017-09-21T10:11:19.026Z'; // jsDate.toUTCString(); var_dump(\DateTime::createFromFormat($format, $value));