PHP错误:在布尔值上调用成员函数setTimeZone()

时间:2018-12-12 07:56:56

标签: php

在返回以微秒为单位的当前时间的函数中遇到以下错误:

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

2 个答案:

答案 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()));
}