PHP 将毫秒转换为日期在特定毫秒内失败 (1425318722000)

PHP Converting milliseconds to date fails for specific millisecond (1425318722000)

所以我正在尝试将毫秒转换为 PHP 中的日期,我认为我的脚本工作正常但对于特定的毫秒值 (1425318722000) 会出现奇怪的行为。

我已经在几个网站上进行了检查,所有网站都返回了有效值...

2015 年 3 月 2 日星期一5:52:02格林威治标准时间下午

2015 年 3 月 2 日星期一 17:52:02

2015 年 3 月 2 日星期一17:52:02格林威治标准时间+0000(格林威治标准时间)

2015 年 3 月 2 日星期一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"
}

事实是您使用的是 'U.u' 掩码,但是当该除法的小数点后结果全为 0 时,.u 从值中丢失

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 需要小数点和后面数字的掩码