Simple PHP timer class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Utility class to enable very simplistic timing. | |
* | |
* Usage example: | |
* | |
* $t = new Timer(); | |
* // do something here | |
* echo $t; | |
* | |
* You can also mark positions: | |
* | |
* $t->mark('Step 1'); | |
* sleep(2.24); | |
* $t->mark(); | |
* usleep(327); | |
* $t->stop(); | |
* echo $t; | |
*/ | |
class Timer | |
{ | |
protected $times = []; | |
protected $started = false; | |
protected $stopped = false; | |
/** | |
* Timer constructor | |
*/ | |
public function __construct() | |
{ | |
$this->times = [$this->getTimestamp('Start timer')]; | |
$this->started = true; | |
$this->stopped = false; | |
} | |
/** | |
* Create a timestamp object | |
* | |
* @param null|string $message | |
* @return object | |
*/ | |
protected function getTimestamp($message = null) | |
{ | |
if (phpversion() < 7) { | |
return (object)[ | |
'time' => microtime(true), | |
'message' => $message | |
]; | |
} | |
return (object)[ | |
'time' => date_create_immutable_from_format('U.u', microtime(true)), | |
'message' => $message | |
]; | |
} | |
/** | |
* Mark the next timer spot | |
* | |
* @param null|string $message | |
* @return $this | |
*/ | |
public function mark($message = null) | |
{ | |
if ($this->stopped) { | |
return $this; | |
} | |
if ($this->started !== true) { | |
throw new \RuntimeException('You have not started a timer'); | |
} | |
$this->times[] = $this->getTimestamp($message); | |
return $this; | |
} | |
/** | |
* Stop the timer | |
* | |
* @return $this | |
*/ | |
public function stop() | |
{ | |
if ($this->stopped) { | |
return $this; | |
} | |
if ($this->started !== true) { | |
throw new \RuntimeException('You have not started a timer'); | |
} | |
$this->times[] = $this->getTimestamp('End timer'); | |
$this->stopped = true; | |
return $this; | |
} | |
/** | |
* Output the timer details. | |
* | |
* If the timer has not been stopped it will just give the output with the | |
* start time and the delta since then. If the timer has been stopped it | |
* will give a fully summary with any marked positions. | |
* | |
* @return string | |
*/ | |
public function __toString() | |
{ | |
if ($this->started !== true) { | |
return 'You have not started a timer'; | |
} | |
try { | |
if (!$this->stopped) { | |
$current = $this->getTimestamp('So far'); | |
return sprintf("Started %s, current delta %s\n", | |
$this->getFormatted($this->times[0]->time), | |
$this->getDiff($current->time, $this->times[0]->time) | |
); | |
} else { | |
$output = ''; | |
$total = count($this->times); | |
for ($i = 0; $i < $total; $i++) { | |
if (!$i) { | |
$output .= sprintf("Started %s\n", $this->getFormatted($this->times[$i]->time)); | |
} else if ($i == ($total - 1)) { | |
$output .= sprintf("Ended %s, total time %s\n", | |
$this->getFormatted($this->times[$i]->time), | |
$this->getDiff($this->times[0]->time, $this->times[$i]->time) | |
); | |
} else { | |
$output .= sprintf("\tΔ %s%s\n", | |
$this->getDiff($this->times[$i-1]->time, $this->times[$i]->time), | |
$this->times[$i]->message ? " ({$this->times[$i]->message})" : '' | |
); | |
} | |
} | |
return $output; | |
} | |
} catch (\Exception $e) { | |
return 'Cannot determine timer: ' . $e->getMessage(); | |
} | |
} | |
/** | |
* Represent the delta between the start and end times. | |
* | |
* @param \DateTimeInterface|float $start | |
* @param \DateTimeInterface|float $end | |
* @return string | |
*/ | |
protected function getDiff($start, $end) | |
{ | |
if ($start instanceof \DateTimeInterface) { | |
$diff = $end->diff($start, true); | |
return $diff->format('%dd %hh %im %s.%Fs'); | |
} | |
$diff = $end - $start; | |
return sprintf('%0dd %0dh %0dm %0.04fs', | |
floor($diff / 86400), | |
($diff / 3600) % 24, | |
($diff / 60) % 60, | |
($diff % 60) + fmod($diff, 1) | |
); | |
} | |
/** | |
* Get formatted date/time. | |
* | |
* @param \DateTimeInterface|float $datetime | |
* @return false|string | |
*/ | |
protected function getFormatted($datetime) | |
{ | |
if ($datetime instanceof \DateTimeInterface) { | |
return $datetime->format('Y-m-d H:i:s'); | |
} | |
return date_format( | |
date_create_from_format('U.u', $datetime), | |
'Y-m-d H:i:s' | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment