time_nanosleep
Delays execution for a given number of seconds and nanoseconds, reporting time left if interrupted.
time_nanosleep(int $seconds, int $nanoseconds): array|bool- Added in PHP 5.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$seconds | int | Whole seconds to wait. Must not be negative. |
$nanoseconds | int | Additional nanoseconds to wait. Must be non-negative and less than 1,000,000,000. |
Return value
array|booltrue on success, false on failure. If a signal interrupted the delay, an array with the keys seconds and nanoseconds holding the remaining time is returned instead.
Errors
Passing a negative seconds value, or a nanoseconds value that is negative or 1,000,000,000 or greater, is rejected as an invalid argument.
time_nanosleep() is the precise cousin of sleep(). You give it a whole-second part and a nanosecond part, and unlike sleep() or usleep() it tells you how much of the delay was left if a signal cut it short.
When to reach for it
- Pacing a loop to a target rate where microsecond drift matters, such as an audio or sensor sampling script.
- Any CLI script that installs signal handlers with
pcntland must resume a partially completed wait. - Delays expressed naturally in nanoseconds alongside
hrtime()measurements.
What trips people up
The return type is the trap. Success is true, failure is false, but an interrupted call returns an array — which is truthy. Writing if (time_nanosleep(1, 0)) { /* slept fully */ } treats an interruption as success. Compare with === true, or check is_array() and sleep the remainder.
Also note that the nanosecond argument must stay below one billion; roll whole seconds into the first argument rather than passing 1_500_000_000. Actual resolution depends on the OS scheduler, so on Windows especially the real pause can be noticeably longer than requested.
Example
When to use it
- Throttling a polling loop to a precise interval such as 250 ms per iteration.
- Resuming the remaining wait after a SIGALRM or SIGINT interrupts a long delay in a daemon.
- Spacing out writes to a rate-limited device or serial port in a CLI tool.
Frequently asked questions
What is the difference between time_nanosleep and usleep?
usleep() takes microseconds and returns nothing useful, while time_nanosleep() takes a seconds plus nanoseconds pair and reports the remaining time when a signal interrupts the delay.
Why does my check on the return value always pass?
An interrupted call returns an array, and arrays are truthy. Use $result === true to test for a fully completed delay.
Can I pass more than one billion nanoseconds?
No. The nanoseconds argument must be less than 1,000,000,000; put whole seconds in the first argument instead.
More examples
Handling an interrupted delay correctly
Without a signal the loop body never runs and only "done" prints, but the pattern shown is what correctly finishes the remaining delay when a signal does interrupt it.
<?php
function waitFully(int $sec, int $nsec): void {
$result = time_nanosleep($sec, $nsec);
while (is_array($result)) {
echo "interrupted, {$result['nanoseconds']}ns left\n";
$result = time_nanosleep($result['seconds'], $result['nanoseconds']);
}
}
waitFully(0, 100_000_000);
echo "done\n";Pacing a loop to a fixed interval
The three ticks land near 100, 200 and 300 milliseconds, showing the delay accumulating at roughly the requested rate with a small scheduler overshoot each time.
<?php
$interval = 100_000_000;
$start = hrtime(true);
for ($i = 1; $i <= 3; $i++) {
time_nanosleep(0, $interval);
$ms = (hrtime(true) - $start) / 1_000_000;
printf("tick %d at %.0f ms\n", $i, $ms);
}
Discussion