phpdatemicrotimeusleep

Stop execution till the beginning of the next hour


I successfully find (i think) how many microseconds have to pass till the beginning of the next hour but usleep() function shows warning

Number of microseconds must be greater than or equal to 0

$min = (integer)date('i');
$sec = (integer)date('s');
list($microsec, $tmp) = explode(' ', microtime());
$microsec = (integer)str_replace("0.", "", $microsec);
$min_dif = 59 - $min;
$sec_dif = 59 - $sec;
$microsec_dif = 100000000 - $microsec;
$dif_in_micro = $sec_dif * 100000000 + $min_dif * 6000000000 + 
$microsec_dif;
echo $dif_in_micro;
usleep($dif_in_micro);

Thanks a lot for your answers i ended up using the following

$seconds_to_wait = 3540 - (integer)date('i') * 60 + 59 - (integer)date('s');
list($microsec, $tmp) = explode(' ', microtime());
$microsec_to_wait = 1000000 - $microsec * 1000000;
sleep($seconds_to_wait);
usleep($microsec_to_wait);
$now = DateTime::createFromFormat('U.u', microtime(true));
file_put_contents("finish_time.txt", $now->format("m-d-Y H:i:s.u") . PHP_EOL, FILE_APPEND);

Solution

  • In your case your time base is not micro seconds, it is 10ns resolution.

    microtime() delivers the time in seconds with 8 decimals. You are stripping the leading 0. and use the eight decimals. You considered this by writing $microsec_dif = 1E8 - $microsec;. You send the result to usleep(), without to compensate for the factor of 100. This gives you a timeout of 100 times of what you intended. And an integer overflow may comes on top.

    usleep takes an integer for the time. The maximum is about 2E9 µs. With that limitation you cannot wait for longer than 2000 seconds for a single call.

    Here my code:

    $TimeNow=microtime(true);
    $SecondsSinceLastFullHour = $TimeNow - 3600*floor($TimeNow/3600);
    //echo ("Wait " .   (3600 - SecondsSinceLastFullHour) . " seconds.");
    $Sleeptime=(3600.0 - $SecondsSinceLastFullHour); //as float
    //Maximum of $Sleeptime is 3600    
    //usleep(1e6*$Sleeptime); //worst case 3600E6 won't fit into integer.
    //...  but 1800E6 does. So lets split the waiting time in to halfes.
    usleep(500000*$Sleeptime);
    usleep(500000*$Sleeptime);