Faced the following error in a function that returns the current time with microseconds:
Fatal error: Call to a member function setTimeZone() on boolean
The code this function is:
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');
}
This error occurs with a small proportion of users (<1%). I know that setTimeZone() can return false if a problem occurs, but how can I avoid this problem in my code? Why does setTimeZone() return false?
I am using PHP Version 7.0.9.
The problem turned out to be that the microtime(true) function sometimes returns a number without a dot and the U.u format does not apply to it. As a result, two solutions were found to solve the problem:
Solution 1: Replace (int) $microtime != $microtime with stripos($microtime, '.')
Solution 2: Wrap the code in a try-catch construct, like this:
try {
getCurrentTime();
} catch (Exception $e) {
// Retry a maximum of 3 times
}
Posted on behalf of OP
The casting to (int) on your ternary statement might be the culprit.
What you are effectively doing is:
$microtime_int != $microtime_float
Which will almost always give you a false. But when it returns TRUE, when you hit the magic sweet spot of $microtime having zeroes after the decimal point, your format U.u will not work.
Since you must have microseconds, then I will suggest catching an error and retrying until you are fine.
This pseudocode should fix your issue:
try{
getCurrentTime();
}catch(e Exception){
retry max 3 times
}
Please see the proof:
Ouput:
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
script:
<?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()));
}
Above fixes, still in very small amount of cases, give me an error. So I fixed it, in rather very creapy way, but if it works, it works:
$microtime = number_format(microtime(true),4,'.','');
Related
I have a form that passes two dates (start and finish) to a PHP script that will add those to a DB. I am having problems validating this. I keep getting the following errors
A non well formed numeric value encountered
This is when I use the following
date("d",$_GET['start_date']);
But when I use the strtotime() function as advised by many sites I get a unix timestamp date of 1/1/1970.
Any ideas how I can get the correct date?
Because you are passing a string as the second argument to the date function, which should be an integer.
string date ( string $format [, int $timestamp = time() ] )
Try strtotime which will Parse about any English textual datetime description into a Unix timestamp (integer):
date("d", strtotime($_GET['start_date']));
This error occurs when you perform calculations with variables that use letters combined with numbers (alphanumeric), for example 24kb, 886ab ...
I had the error in the following function
function get_config_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last) {
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $this->fix_integer_overflow($val);
}
The application uploads images but it didn't work, it showed the following warning:
Solution: The intval() function extracts the integer value of a variable with alphanumeric data and creates a new variable with the same value but converted to an integer with the intval() function. Here is the code:
function get_config_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
$intval = intval(trim($val));
switch($last) {
case 'g':
$intval *= 1024;
case 'm':
$intval *= 1024;
case 'k':
$intval *= 1024;
}
return $this->fix_integer_overflow($intval);
}
The function fix_integer_overflow
// Fix for overflowing signed 32 bit integers,
// works for sizes up to 2^32-1 bytes (4 GiB - 1):
protected function fix_integer_overflow($size) {
if ($size < 0) {
$size += 2.0 * (PHP_INT_MAX + 1);
}
return $size;
}
$_GET['start_date'] is not numeric is my bet, but an date format not supported by strtotime. You will need to re-format the date to a workable format for strtotime or use combination of explode/mktime.
I could add you an example if you'd be kind enough to post the format you currently receive.
I ran into this same situation (in my case with a date value in a custom PHP field in a Drupal view), and what worked for me was using intval instead of strtotime to turn the value into an integer - because it basically was a timestamp, but in the form of a string rather than an integer. Obviously that won't be the case for everyone, but it might be worth a try.
This helped me a lot -
$new_date = date_format(date_create($old_date), 'Y-m-d');
Here, date_create() provides you a date object for a given date & date_format() will set it in a given format.
for example,
<?php
$date = date_create("13-02-2013"); // DateTime Object ( [date] => 2013-02-13 00:00:00.000000 [timezone_type] => 3 [timezone] => America/New_York )
echo date_format($date,"Y-m-d"); // 2013-02-13
?>
This is an old question, but there is another subtle way this message can happen. It's explained pretty well here, in the docs.
Imagine this scenerio:
try {
// code that triggers a pdo exception
} catch (Exception $e) {
throw new MyCustomExceptionHandler($e);
}
And MyCustomExceptionHandler is defined roughly like:
class MyCustomExceptionHandler extends Exception {
public function __construct($e) {
parent::__construct($e->getMessage(), $e->getCode());
}
}
This will actually trigger a new exception in the custom exception handler because the Exception class is expecting a number for the second parameter in its constructor, but PDOException might have dynamically changed the return type of $e->getCode() to a string.
A workaround for this would be to define you custom exception handler like:
class MyCustomExceptionHandler extends Exception {
public function __construct($e) {
parent::__construct($e->getMessage());
$this->code = $e->getCode();
}
}
If the error is at the time of any calculation, double check that the values does not contains any comma(,). Values must be only in integer/ float format.
if $_GET['start_date'] is a string then convert it in integer or double to deal numerically.
$int = (int) $_GET['start_date']; //Integer
$double = (double) $_GET['start_date']; //It takes in floating value with 2 digits
in the name of the universe programmer
in my case i receive this error
"Notice: A non well formed numeric value encountered in"
my code with above error:
$end_suggest_time = $rowone['start_suggest_time'] + (24 * 3600);
when i add (int) in the previous of $rowone['start_suggest_time'] I don't receive this error
"Notice: A non well formed numeric value encountered in"
$end_suggest_time = (int) $rowone['start_suggest_time'] + (24 * 3600);
In my case when getting error:
A non well formed numeric value encountered
When my code is like this
if (date('y-m-d H:i:s') - $user_token['created_at'] < (60 * 60 * 24)) {
...
}
And my fixing code
date_default_timezone_set('Asia/Jakarta');
if (strtotime(date('y-m-d H:i:s')) - strtotime($user_token['created_at']) < (60 * 60 * 24)) {
...
}
You need to set the time zone using date_default_timezone_set().
I have a form that passes two dates (start and finish) to a PHP script that will add those to a DB. I am having problems validating this. I keep getting the following errors
A non well formed numeric value encountered
This is when I use the following
date("d",$_GET['start_date']);
But when I use the strtotime() function as advised by many sites I get a unix timestamp date of 1/1/1970.
Any ideas how I can get the correct date?
Because you are passing a string as the second argument to the date function, which should be an integer.
string date ( string $format [, int $timestamp = time() ] )
Try strtotime which will Parse about any English textual datetime description into a Unix timestamp (integer):
date("d", strtotime($_GET['start_date']));
This error occurs when you perform calculations with variables that use letters combined with numbers (alphanumeric), for example 24kb, 886ab ...
I had the error in the following function
function get_config_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last) {
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $this->fix_integer_overflow($val);
}
The application uploads images but it didn't work, it showed the following warning:
Solution: The intval() function extracts the integer value of a variable with alphanumeric data and creates a new variable with the same value but converted to an integer with the intval() function. Here is the code:
function get_config_bytes($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
$intval = intval(trim($val));
switch($last) {
case 'g':
$intval *= 1024;
case 'm':
$intval *= 1024;
case 'k':
$intval *= 1024;
}
return $this->fix_integer_overflow($intval);
}
The function fix_integer_overflow
// Fix for overflowing signed 32 bit integers,
// works for sizes up to 2^32-1 bytes (4 GiB - 1):
protected function fix_integer_overflow($size) {
if ($size < 0) {
$size += 2.0 * (PHP_INT_MAX + 1);
}
return $size;
}
$_GET['start_date'] is not numeric is my bet, but an date format not supported by strtotime. You will need to re-format the date to a workable format for strtotime or use combination of explode/mktime.
I could add you an example if you'd be kind enough to post the format you currently receive.
I ran into this same situation (in my case with a date value in a custom PHP field in a Drupal view), and what worked for me was using intval instead of strtotime to turn the value into an integer - because it basically was a timestamp, but in the form of a string rather than an integer. Obviously that won't be the case for everyone, but it might be worth a try.
This helped me a lot -
$new_date = date_format(date_create($old_date), 'Y-m-d');
Here, date_create() provides you a date object for a given date & date_format() will set it in a given format.
for example,
<?php
$date = date_create("13-02-2013"); // DateTime Object ( [date] => 2013-02-13 00:00:00.000000 [timezone_type] => 3 [timezone] => America/New_York )
echo date_format($date,"Y-m-d"); // 2013-02-13
?>
This is an old question, but there is another subtle way this message can happen. It's explained pretty well here, in the docs.
Imagine this scenerio:
try {
// code that triggers a pdo exception
} catch (Exception $e) {
throw new MyCustomExceptionHandler($e);
}
And MyCustomExceptionHandler is defined roughly like:
class MyCustomExceptionHandler extends Exception {
public function __construct($e) {
parent::__construct($e->getMessage(), $e->getCode());
}
}
This will actually trigger a new exception in the custom exception handler because the Exception class is expecting a number for the second parameter in its constructor, but PDOException might have dynamically changed the return type of $e->getCode() to a string.
A workaround for this would be to define you custom exception handler like:
class MyCustomExceptionHandler extends Exception {
public function __construct($e) {
parent::__construct($e->getMessage());
$this->code = $e->getCode();
}
}
If the error is at the time of any calculation, double check that the values does not contains any comma(,). Values must be only in integer/ float format.
if $_GET['start_date'] is a string then convert it in integer or double to deal numerically.
$int = (int) $_GET['start_date']; //Integer
$double = (double) $_GET['start_date']; //It takes in floating value with 2 digits
in the name of the universe programmer
in my case i receive this error
"Notice: A non well formed numeric value encountered in"
my code with above error:
$end_suggest_time = $rowone['start_suggest_time'] + (24 * 3600);
when i add (int) in the previous of $rowone['start_suggest_time'] I don't receive this error
"Notice: A non well formed numeric value encountered in"
$end_suggest_time = (int) $rowone['start_suggest_time'] + (24 * 3600);
In my case when getting error:
A non well formed numeric value encountered
When my code is like this
if (date('y-m-d H:i:s') - $user_token['created_at'] < (60 * 60 * 24)) {
...
}
And my fixing code
date_default_timezone_set('Asia/Jakarta');
if (strtotime(date('y-m-d H:i:s')) - strtotime($user_token['created_at']) < (60 * 60 * 24)) {
...
}
You need to set the time zone using date_default_timezone_set().
I am troubleshooting a search bar to return rows within a period chosen from 'To' and 'From' datepickers.
I initially got this error :
Error: Method Doctrine\ORM\Query\Expr\Comparison::__toString() must not throw an exception, caught Symfony\Component\Debug\Exception\ContextErrorException: Catchable Fatal Error: Object of class DateTime could not be converted to string
I converted the relevant query to a string using ->format() function:
if (is_array($value) && isset($value['to'])) {
$to = \DateTime::createFromFormat('d/m/Y H:i:s', $value['from'] . ' 23:59:59');
var_dump($value, $to);die;
if ($to <> false) {
$query->andWhere(
$query->expr()->lte($path, $to->format('Y-m-d H:i:s'))
);
}
}
Now doctrine throws the following error:
[Syntax Error] line 0, col 977: Error: Expected end of string, got '00'
Is there something else I need to do to format the date to make it acceptable to the querybuilder? I've tried using / instead of : but this causes an issue.
If I recall correctly, you should either use literal(), or query parameter. And since the lte argument is not constant, using literal() is highly discouraged (due to potential SQL injection).
Anyway, something like this should probably work:
if (is_array($value) && isset($value['to'])) {
if (is_array($value) && isset($value['to'])) {
$to = \DateTime::createFromFormat('d/m/Y H:i:s', $value['from'] . ' 23:59:59');
if ($to <> false) {
$query->andWhere($query->expr()->lte($path, ':to'));
$query->setParameter('to', $to->format('Y-m-d H:i:s'));
}
}
Does it work?
Hope it helps...
I have a code which is working on my localhost but in server it throws error.
the error is: Fatal error: Uncaught exception 'Exception' with message 'DateTime::__construct(): Failed to parse time string (#1645.0000000006) at position 14 (0): Unexpected character
my code is:
function secondsToTime($seconds)
{
$arr = array();
$dtF = new DateTime('#0');
$dtT = new DateTime("#$seconds");
$arr[0] = $dtF->diff($dtT)->format('%h');
$arr[1] = $dtF->diff($dtT)->format('%i');
$arr[2] = $dtF->diff($dtT)->format('%s');
return $arr;
}
print_r(secondsToTime("1645.0000000006"));
what is the problem? thanks everyone
Apparently handling of microseconds changed around PHP 7.1 and PHP accepts decimal values as valid timestamps starting with that version, but not before. If you have to make it compatible with previous versions, you need to cast your float to an int:
$dtT = new DateTime('#' . (int)$seconds);
I have this code which is showing this error in the logs. Any ideas why?
PHP Notice: Undefined offset: 1
$microtime = microtime(true);
list($time,$mili) = explode(".", $microtime);
EDIT:
Sorry forgot to mention that this error doesn't happen every time, I just noticed it in the logs. Maybe it only happens when there are no milliseconds
Example output of microtime: 1418114280.8363
A bit too long for a comment, but (as an alternative) try using
$microtime = microtime(true);
$time = floor($microtime);
$mili = fmod($microtime, 1);
and see what result this gives
It works fine check it
echo $microtime = microtime(true);
print_r(explode(".", $microtime));
list($time,$mili) = explode(".", $microtime);
print_r($time);
echo '---';
print_r($mili);