PHP Преобразование миллисекунд в дату не удается для определенной миллисекунды (1425318722000)

Итак, я пытаюсь преобразовать миллисекунды в дату в PHP, и я думал, что сценарий, который у меня был, работает нормально, но дает странное поведение для определенного значения миллисекунды (1425318722000).

Я проверил это на нескольких веб-сайтах, и все они возвращаются с допустимым значением...

Понедельник, 2 марта 2015 г., 17:52:02 по Гринвичу

Пн 02 мар 2015 17:52:02

Пн, 02 марта 2015 г., 17:52:02 GMT+0000 (GMT)

пн, 02 марта 2015 г., 17:52:02 по Гринвичу

Любая идея, почему это происходит, возможно, это ошибка PHP?

php -r "var_dump(DateTime::createFromFormat('U.u', 1425318721999/1000));"
object(DateTime)#1 (3) {
  ["date"]=>
  string(19) "2015-03-02 17:52:01"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "+00:00"
}

php -r "var_dump(DateTime::createFromFormat('U.u', 1425318722000/1000));"
bool(false)

php -r "var_dump(DateTime::createFromFormat('U.u', 1425318722001/1000));"
object(DateTime)#1 (3) {
  ["date"]=>
  string(19) "2015-03-02 17:52:02"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "+00:00"
}

php -r "var_dump(DateTime::createFromFormat('U.u', 1425318722002/1000));"
object(DateTime)#1 (3) {
  ["date"]=>
  string(19) "2015-03-02 17:52:02"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "+00:00"
}

php -r "var_dump(DateTime::createFromFormat('U.u', 1425318722003/1000));"
object(DateTime)#1 (3) {
  ["date"]=>
  string(19) "2015-03-02 17:52:02"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "+00:00"
}

php -r "var_dump(DateTime::createFromFormat('U.u', 1425318722004/1000));"
object(DateTime)#1 (3) {
  ["date"]=>
  string(19) "2015-03-02 17:52:02"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "+00:00"
}

php -r "var_dump(DateTime::createFromFormat('U.u', 1425318722005/1000));"
object(DateTime)#1 (3) {
  ["date"]=>
  string(19) "2015-03-02 17:52:02"
  ["timezone_type"]=>
  int(1)
  ["timezone"]=>
  string(6) "+00:00"
}

person Carlton    schedule 24.04.2015    source источник
comment
Я думаю, мне следует сделать что-то вроде php -r var_dump(DateTime::createFromFormat('U', round(1425318722001/1000)));   -  person Carlton    schedule 24.04.2015
comment
Может ли DateTime хранить миллисекунды?   -  person Salman A    schedule 24.04.2015


Ответы (1)


Это тот факт, что вы используете маску 'U.u', но .u теряется из значения, когда результатом является все 0 после десятичной точки для этого деления.

for($ms = 1425318721999; $ms <= 1425318722001; ++$ms) {
    var_dump(DateTime::createFromFormat('U.u', sprintf('%14.3f', $ms/1000)));
}

Будет работать, потому что вы используете sprintf(), чтобы заставить эти нули сохраняться после десятичной точки

for($ms = 1425318721999; $ms <= 1425318722001; ++$ms) {
    var_dump(DateTime::createFromFormat('U', floor($ms/1000)));
}

также будет работать, но вы потеряете точность в миллисекундах

В качестве некоторого объяснения:

public static DateTime DateTime::createFromFormat ( string $format , string $time [, DateTimeZone $timezone ] )

createFromFormat() ожидает строку в качестве второго аргумента, поэтому PHP свободно переводит результат вашего деления в строку, а значение с плавающей запятой, такое как 1425318722.000, будет преобразовано в строку "1425318722" без десятичной точки или следующих нулей, поэтому это не так. не соответствует маске U.u, для которой требуется десятичная точка и последующие цифры

person Mark Baker    schedule 24.04.2015
comment
Только что узнал то же самое! - person marijnz0r; 24.04.2015
comment
Спасибо, Марк, хорошее объяснение ... кстати, надеюсь, вы не возражаете, скопировав идею своего сертификационного значка ZF. - person Carlton; 24.04.2015
comment
Просто добавил еще немного пояснений о том, почему десятичная точка и цифры имеют значение и теряются - person Mark Baker; 24.04.2015
comment
И я полностью за продвижение сертификатов (хотя мне интересно, стоит ли мне сдавать экзамен ZCE 5.5 или подождать, пока не появится новый блестящий ZCE для PHP 7) - person Mark Baker; 24.04.2015
comment
Да, я знаю Сэнди, там жили кузены. Мы играли против школы Бедфорд в регби, им не нравилось проигрывать государственной школе :D - person Carlton; 24.04.2015
comment
Я, вероятно, пересдам сертификацию PHP 7, всегда полезно освежить в памяти новые дополнения к языку. - person Carlton; 24.04.2015
comment
Давайте продолжим обсуждение в чате. - person Carlton; 24.04.2015