Difference with microseconds precision between two DateTime in PHP
Asked Answered
S

6

8

I can get a datetime with microseconds in PHP with a workaround as:

list($usec, $sec) = explode(" ", microtime());
echo date("Y-m-d\TH:i:s", $sec) . "." . floatval($usec)*pow(10,6);

I need the difference with microseconds between two datetimes, can't get a workaround for:

$datetime1 = new DateTime('2013-08-14 18:49:58.606');
$datetime2 = new DateTime('2013-08-14 22:27:19.272');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%h hours %i minutes %s seconds %u microseconds');

DateInterval::format doesn't has the format character %u or equivalent for microseconds.

Anyone knows a workaround for this?

Saunders answered 15/8, 2013 at 15:43 Comment(6)
DateInterval does not support microseconds. And also DateTime does not support them. All points that you have to do all related calculations manually to achieve such precision.Emitter
DateTime::createFromFormat() added the u format fairly recently (PHP 5.5?), though I can't find any evidence that it's supported by DAteIntervalKythera
@Baldrs I know, but with time functions is easy to make errors, I'm asking for a workaround, a non standard solution.Saunders
@MarkBaker I'm using PHP 5.5.1 %u is printed as suchSaunders
Do you expect the same format as Y-m-d H:i:s.(microseconds)? Then you can get microseconds using a regex, calculate difference between them manually and insert it inside format string.Emitter
For reference, PHP 7.1 has added F and f for microseconds (with and without leading zeroes respectively) to DateInterval::format.Krystynakshatriya
P
4

Manually creating a DateTime object with micro seconds:

$d = new DateTime("15-07-2014 18:30:00.111111");

Getting a DateTime object of the current time with microseconds:

$d = date_format(new DateTime(),'d-m-Y H:i:s').substr((string)microtime(), 1, 8);

Difference between two DateTime objects in microseconds (e.g. returns: 2.218939)

//Returns the difference, in seconds, between two datetime objects including
//the microseconds:

function mdiff($date1, $date2){
//Absolute val of Date 1 in seconds from  (EPOCH Time) - Date 2 in seconds from (EPOCH Time)
$diff = abs(strtotime($date1->format('d-m-Y H:i:s.u'))-strtotime($date2->format('d-m-Y H:i:s.u')));

//Creates variables for the microseconds of date1 and date2
$micro1 = $date1->format("u");
$micro2 = $date2->format("u");

//Absolute difference between these micro seconds:
$micro = abs($micro1 - $micro2);

//Creates the variable that will hold the seconds (?):
$difference = $diff.".".$micro;

return $difference;
}

Essentially it finds the difference for the DateTime Objects using strtotime and then adding the extra microseconds on.

Pronuba answered 15/7, 2014 at 14:59 Comment(3)
Why are you using strtotime($date1->format('d-m-Y H:i:s.u')) instead of strtotime($date1->format('d-m-Y H:i:s'))?Kimmel
I guess it doesn't make a difference as the u value will always be the samePronuba
your code have bug, for these data: 2021-01-27 11:56:19.198768 and 2021-01-27 11:56:20.199023 , return 1.255 , but correction was: 1.000255Dialectology
P
6
/**
 * returns the difference in seconds.microseconds(6 digits) format between 2 DateTime objects 
 * @param DateTime $date1
 * @param DateTime $date2
 */
function mdiff($date1, $date2){
    return number_format(abs((float)$date1->format("U.u") - (float)$date2->format("U.u")), 6);
}
Privity answered 21/5, 2018 at 0:37 Comment(1)
works well, for these data: 2021-01-27 11:56:19.198768 and 2021-01-27 11:56:20.199023 , return 1.000255Dialectology
P
4

Manually creating a DateTime object with micro seconds:

$d = new DateTime("15-07-2014 18:30:00.111111");

Getting a DateTime object of the current time with microseconds:

$d = date_format(new DateTime(),'d-m-Y H:i:s').substr((string)microtime(), 1, 8);

Difference between two DateTime objects in microseconds (e.g. returns: 2.218939)

//Returns the difference, in seconds, between two datetime objects including
//the microseconds:

function mdiff($date1, $date2){
//Absolute val of Date 1 in seconds from  (EPOCH Time) - Date 2 in seconds from (EPOCH Time)
$diff = abs(strtotime($date1->format('d-m-Y H:i:s.u'))-strtotime($date2->format('d-m-Y H:i:s.u')));

//Creates variables for the microseconds of date1 and date2
$micro1 = $date1->format("u");
$micro2 = $date2->format("u");

//Absolute difference between these micro seconds:
$micro = abs($micro1 - $micro2);

//Creates the variable that will hold the seconds (?):
$difference = $diff.".".$micro;

return $difference;
}

Essentially it finds the difference for the DateTime Objects using strtotime and then adding the extra microseconds on.

Pronuba answered 15/7, 2014 at 14:59 Comment(3)
Why are you using strtotime($date1->format('d-m-Y H:i:s.u')) instead of strtotime($date1->format('d-m-Y H:i:s'))?Kimmel
I guess it doesn't make a difference as the u value will always be the samePronuba
your code have bug, for these data: 2021-01-27 11:56:19.198768 and 2021-01-27 11:56:20.199023 , return 1.255 , but correction was: 1.000255Dialectology
S
2

Since PHP 7.1 (2016-12-01) there is %f and %F for microseconds precision, but just from 7.2 (2017-11-30) it is safe to use due to the critical date bugs in 7.1 (Tested)

The working example:

<?php
$datetime1 = new DateTime('2013-08-14 18:49:58.800');
$datetime2 = new DateTime('2013-08-14 22:27:19.900');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%h hours %i minutes %s seconds %f microseconds');

PD: Answering my own question posted 4 years before the existence of %f

Saunders answered 30/1, 2021 at 8:13 Comment(0)
P
0

I had to replace this

$micro = abs($micro1 - $micro2);

with this

str_pad(abs($micro1 - $micro2), 6, '0', STR_PAD_LEFT);

to get the correct microtime for some reason.

Phenanthrene answered 9/6, 2016 at 19:43 Comment(0)
R
0
function mdiff($date1, $date2){
  //Absolute val of Date 1 in seconds from  (EPOCH Time) - Date 2 in seconds from (EPOCH Time)
  $diff = abs(strtotime($date1->format('d-m-Y H:i:s.u'))-strtotime($date2->format('d-m-Y H:i:s.u')));

  //Creates variables for the microseconds of date1 and date2
  $micro1 = $date1->format("u");
  $micro2 = $date2->format("u");

  //Difference between these micro seconds:
  $diffmicro = $micro1 - $micro2;

  list($sec,$micro) = explode('.',((($diff) * 1000000) + $diffmicro )/1000000);

  //Creates the variable that will hold the seconds (?):
  $difference = $sec . "." . str_pad($micro,6,'0');

  return $difference;
}

This function returns the correct difference

Example:
    Start:"2016-10-27 17:17:52.576801"
    End:"2016-10-27 17:18:00.385801"
    Difference:"7.809000"

    Old Function:
    Difference:"8.191000"
Revels answered 27/10, 2016 at 15:12 Comment(1)
your code have bug, for these data: 2021-01-27 11:56:19.198768 and 2021-01-27 11:56:20.199023 , return 0.998759 , but correction was: 1.000255Dialectology
S
0

Shorter version with float returned

function diff(\DateTimeInterface $a, \DateTimeInterface $b): float
{
    return ($a->getTimestamp() - $b->getTimestamp()) + ($a->format("u") - $b->format("u")) / 1000000;
}
Spinthariscope answered 28/7, 2020 at 6:52 Comment(1)
for these data: 2021-01-27 11:56:19.198768 and 2021-01-27 11:56:20.199023 , return -1.000255 , I thinks better return positive number.Dialectology

© 2022 - 2025 — McMap. All rights reserved.