Log in
The 6th generation of atomic frequency standards at NBS
NBS-6 is 6 metres long and keeps time with an accuracy
of about 3 millionths of a second per year.
2014-03-14 10:30
Public Domain — courtesy of U.S. federal government

µTime PHP class


Based on PHP's built-in microtime() function; this PHP class generates, compares and displays Unix time stamps with microsecond precision.

PHP source code

<?php	namespace AAABIT;
 *║ https://aaabit.com/products/microtime-php-class/
 *║ PHP class for generating, comparing and displaying
 *║	unix time stamps with a microsecond component
 *║ AUTHOR:	Matthew Slyman @ AAABIT.com
 *║ COPYRIGHT:	© AAABIT 2012–2016 - permissively licensed under CC (CC-BY-4.0-International)
 *║ DATE:	2012-04-20 - 2012-07-20, 2014-09-09 (v1.0.1), 2015-12-22 (v2.0.0)
 *║ VERSION:	2.0.0 (tested by author, working)
 * FROM PHP SITE: jamie at bishopston dot net: "For timing, you should really use clock_gettime(2) with the CLOCK_MONOTONIC flag set." //http://uk3.php.net/manual/en/function.microtime.php
 * POSSIBLE ALTERNATIVE: http://codeaid.net/php/calculate-script-execution-time-(php-class)
 * CHANGES or backward-compatible augmentations may be made to this code to bring this into line with official standards of PHP's new built-in DateTime class.
 * https://bugs.php.net/bug.php?id=62917 //←ON WINDOWS…
 * https://bugs.php.net/bug.php?id=69961 //←NO METHOD OVERLOADING! This makes implementing a really clean version of this, into a nightmare. µTime+µTimeInterval=µTime; µTimeInterval+µTime=µTime; µTimeInterval+µTimeInterval=µTimeInterval (can't do it cleanly without method overloading!!!) PLEASE?
 * PHP v7.1 now includes microseconds in constructor of built-in \DateTime class! These classes will potentially be deprecated in favour of the built-in \DateTime,\DateTimeZone etc. classes. See: http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.datetime-microseconds
if(PHP_INT_MAX<2**60){throw new \Exception('64-bit PHP is required for µTime class!');}
//if(PHP_VERSION_ID<70000){throw new \Exception('PHP version ≥ 7.0.0 required!');}//Probably not required: syntax error anyway if you don't have PHP7?
abstract class µTimePrimitive{
	protected $µs;	//Microsecond component — ⋙using 64-bit arithmetic, we could merge these fields together, simplifying much of the arithmetic…
	//Methods for reading member variables (seconds and microseconds components).
	public function s():int			{return ($this->µs-$this->µs%1000000)/1000000;}
	public function ms():int		{return ($this->µs%1000000-$this->µs%1000)/1000;}
	public function µs():int		{return $this->µs%1000000;}
	public function sgn():int		{return ($this->µs>0) - ($this->µs<0);}//⋙PHP7: $this->µs<=>0;
	public function int_µs():int		{return $this->µs;}
	//Method "float()" is typically used for DURATIONS and INTERVALS. Useful for inserting time interval measurements into MySQL or any other database system (see comments below on "ux_text...()" methods).⋙Try moving this into µTimeInterval object? Potentially breaks backwards compatibility…
	public function float_s():float		{return ((float)$this->µs * 10**-6);}	//Example method call:		$µTime->float_s();
	public function string():string		{return '0.'.$this->µs().' '.$this->s();}
	//Methods "gt|ge|eq|le|lt" are comparator functions. They return Boolean true or false. These methods apply to µTime (absolute points in time, where comparison reveals which point in time is earlier/later), or to µTimeInterval (durations, where comparison reveals which duration is longer/shorter).
	public function gt(self $cmp):bool	{return ($this->µs > $cmp->µs);}//⋘Would benefit from PHP magic methods for comparison!
	public function ge(self $cmp):bool	{return ($this->µs >=$cmp->µs);}
	public function eq(self $cmp):bool	{return ($this->µs===$cmp->µs);}
	public function le(self $cmp):bool	{return ($this->µs <=$cmp->µs);}
	public function lt(self $cmp):bool	{return ($this->µs < $cmp->µs);}
	public function add(µTimeInterval $step,$in_place_edit=false){if($in_place_edit){$base=$this;}else{$base=clone $this;}$base->µs+=$step->µs;return $base;}
	public function sub(µTimeInterval $step,$in_place_edit=false){if($in_place_edit){$base=$this;}else{$base=clone $this;}$base->µs-=$step->µs;return $base;}

//⋙Now that \DateTime is starting to support microseconds properly, we might replace many µTime instances with \DateTime for "plain vanilla PHP" wherever possible (reduce dependencies on anything except the stable core!)
class µTime extends µTimePrimitive{		//µ symbol is part of ASCII character set, and seems to work fine in PHP.//Absolute point in time: this is basically like a µTimeInterval, based on a fixed starting point.
	public function __construct(int $s,int $µs,bool $test=false){if($test){var_dump($s);var_dump($µs);}$this->µs=$s*10**6+$µs;}	//Example instantiation:	$mtimevar = new µTime($ux_s, $µs);//BUG FIXED:WAS:$this->µs=\substr($µs,2,6);!!! Perhaps a relic of an earlier version where constructor was only based on seconds, with decimal places?
	public function __toString():string	{return $this->text_with_µs();}
	public static function current():µTime	{return self::from(\microtime());}		//Example static method call:	µTime::current();	//⋘RENAMED FROM current_ux(): breaking change!
	public static function from(string $µTime):µTime{list($µs,$s)=\explode(' ',$µTime);$µs=(int)\str_pad(\substr($µs,2,6),6,'0');return new µTime($s,$µs);}	//Example static method call:	µTime::from(\microtime());
	public static function fromDateTime(\DateTime $abs_dt):µTime{$datetime=clone $abs_dt;$datetime->setTimezone(new \DateTimeZone('UTC'));return new µTime((int)$datetime->format('U'),(int)$datetime->format('u'));}
	public static function fromUnixUTC(int $timestamp):µTime{return new µTime($timestamp,0);}
	public static function fromFloat(float $microtime):µTime{$intpart=(int)\floor($microtime);$frcpart=(int)\floor(($microtime-$intpart)*10**6);return new µTime($intpart,$frcpart);}//e.g. from $_SERVER['REQUEST_TIME_FLOAT']//≫WARNING: After about September in the year 2112, 'double' precision floating-point microsecond timestamps (representing up to 2⁵² microseconds since 1970-01-01 00:00), will become slightly less precise.//⋘Do we need the \floor() function here, or is (int) type casting sufficient — does this include the \floor() function?
	public function DateTime():\DateTime{return new \DateTime($this->text_with_µs(),new \DateTimeZone('UTC'));}
	//Methods "text...()" are for returning Unix time stamp strings in canonical SQL format, with or without millisecond/ microsecond component (e.g. for insertion into an SQL database.) Note that actual stored precision depends on database system and field format: e.g. MySQL < v5.7, or MariaDB < v10, ignores the microsecond component.
	public function text():string		{return \gmdate('Y-m-d H:i:s',$this->s());}//⋙IS THIS prone to Y2k38 bug?If so, change from "\gmdate()" to use "DateTime" class.
	public function text_with_µs():string	{return $this->text().'.'.\sprintf('%06d',$this->µs());}
	public function text_with_ms():string	{return $this->text().'.'.\sprintf('%03d',$this->ms());}
	//Methods for generating µTimeInterval…
	public function elapsed_since(µTime $start):µTimeInterval{return new µTimeInterval($start,$this);}//Example method call:	$µTime2->elapsed_since($utime1);

class µTimeInterval extends µTimePrimitive{//If PHP DateTime, DateInterval classes didn't have so many bugs/shortcomings in comparison (with microseconds); we wouldn't have to write these alternatives… When PHP7 services our requirements, we might drop these classes and replace them with the native objects.
//	protected $s;	//Seconds component
//	protected $µs;	//Microseconds component
	public function __construct(µTime $start,µTime $end){$this->µs=$end->µs-$start->µs;return $this;}
	public function __toString():string	{return $this->dhms_text();}
	//Methods "...hms_text()" are for durations - or intervals - between two µTime time stamps.
	public function neg():µTimeInterval	{$base=clone $this;$base->µs=-1*$base->µs;return $base;}
	public function hms_text():string	{$ux=\abs($this->s());$s=$ux%60;$m=(($ux-$s)/60)%60;$h=($ux-($ux%3600))/3600;return ($this->sgn()===-1?'-':'').'['.$h.':'.\sprintf('%02d',$m).':'.\sprintf('%02d',$s).'].'.\sprintf('%06d',\abs($this->µs())).'µs';}//⋘Might change output format - this is for DISPLAY
	public function dhms_text():string	{$ux=\abs($this->s());$s=$ux%60;$m=(($ux-$s)/60)%60;$h=(($ux-($ux%3600))/3600)%24;$d=($ux-($ux%86400))/86400;return ($this->sgn()===-1?'-':'').($d>0 ? $d.'d+[' : '[').\sprintf('%02d',$h).':'.\sprintf('%02d',$m).':'.\sprintf('%02d',$s).'].'.\sprintf('%06d',\abs($this->µs())).'µs';}//⋘Might change output format - this is for DISPLAY
	public function DateInterval()		{throw new \Exception('Not implemented yet!');}
	//This class inherits useful methods: float, gt, ge, eq, le, lt, hms_text, dhms_text

Example output

string(26) "2018-12-17 02:53:58.372252"


Creative Commons Licence µTime PHP class by AAABIT is licensed under a CC-BY-4.0 International Licence. We supply µTime PHP class free of charge on these conditions.

Attribution of code origin & licence details within your source code is sufficient. Please retain our copyright information comment block for this purpose. Please do not redistribute our code via publicly accessible networks, except as part of a derivative work that adds significant value to what we have done. To suggest incremental improvements, please contact us.

Authors and contributors

Written by Matthew Slyman. Incorporates work by Alex Stetsenko and advice from StackOverflow.