Код говорит миллион слов:
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));