在返回以微秒为单位的当前时间的函数中遇到以下错误:
Fatal error: Call to a member function setTimeZone() on boolean
此函数的代码为:
public static function getCurrentTime() {
$microtime = microtime(true);
$time = DateTime::createFromFormat('U.u', (int) $microtime != $microtime ? $microtime : $microtime + 0.001);
$time->setTimeZone(new DateTimeZone(date_default_timezone_get()));
return $time->format('Y-m-d H:i:s.u');
}
只有一小部分用户(<1%)发生此错误。我知道如果发生问题,setTimeZone()
可以返回false
,但是如何避免代码中出现此问题?为什么setTimeZone()
返回false
?
我正在使用PHP版本7.0.9
。
编辑:
原来的问题是,microtime(true)
函数有时返回不带点的数字,而U.u
格式不适用于该数字。结果,找到了两种解决方案来解决该问题:
解决方案1:将(int) $microtime != $microtime
替换为stripos($microtime, '.')
解决方案2:将代码包装在try-catch构造中,如下所示:
try {
getCurrentTime();
} catch (e Exception) {
// Retry a maximum of 3 times
}
谢谢大家帮助我解决问题。尤其是@UnamataSanatarai
答案 0 :(得分:2)
原来的问题是,microtime(true)
函数有时返回不带点的数字,而U.u
格式不适用于该数字。结果,找到了两种解决方案来解决该问题:
解决方案1:将(int) $microtime != $microtime
替换为stripos($microtime, '.')
解决方案2:将代码包装在try-catch构造中,如下所示:
try {
getCurrentTime();
} catch (Exception $e) {
// Retry a maximum of 3 times
}
代表OP发布
答案 1 :(得分:0)
在三元语句上强制转换为(int)
可能是罪魁祸首。
您有效执行的操作是:
$microtime_int != $microtime_float
几乎总是会给你一个错误。但是,当它返回TRUE时,当您达到$ microtime的神奇甜蜜点,小数点后为零时,您的格式U.u
将不起作用。
由于您必须有微秒,因此我建议捕获一个错误并重试,直到您一切都好为止。
此伪代码应解决您的问题:
try{
getCurrentTime();
}catch(e Exception){
retry max 3 times
}
请参阅证明
输出:
1544603355.9997
1544603355.9998
1544603355.9998
1544603355.9999
1544603355.9999
1544603355.9999
1544603356
PHP Fatal error: Uncaught Error: Call to a member function setTimeZone() on boolean in a.php:6
Stack trace:
#0 {main}
thrown in a.php on line 6
脚本:
<?php
for ($i = 0; $i <= 999999; $i++){
$microtime = microtime(true);
echo $microtime . "\n";
$time = DateTime::createFromFormat('U.u', (int) $microtime != $microtime ? $microtime : $microtime + 0.001);
$time->setTimeZone(new DateTimeZone(date_default_timezone_get()));
}