'Modify microseconds of a PHP DateTime object

I have a PHP DateTime object with microseconds created as follows:

$time = microtime(true);
$microseconds = sprintf('%06d', ($time - floor($time)) * 1000000);

$dt = new DateTime(date('Y-m-d H:i:s.' . $microseconds, $time));

How can I modify the microseconds value of $dt, without creating a completely new DateTime instance?



Solution 1:[1]

You can't.

There are three methods that can modify the value of a DateTime instance: add, sub and modify. We can rule out add and sub immediately because they work in terms of a DateInterval which does not have sub-second precision.

modify accepts a string in one of the standard recognized formats. Of those formats, only the relative ones are of interest here because the other ones work in an absolute manner; and there is no relative format that allows tweaking the msec part (that unit is not recognized).

Solution 2:[2]

This seems to have been available since 7.1.0-rc4

$dt = new DateTime('2020-01-01 0:00');
$dt->modify('+500 ms'); // Milliseconds.
$dt->modify('+123456 usec'); // Microseconds.
$dt->modify('+123456 microseconds'); // This works too.

Can't find it in the PHP manual though.

Solution 3:[3]

as of PHP 7.1 DateTime::setTime() supports microseconds.

Solution 4:[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){
    $date1sec = strtotime($date1->format('d-m-Y H:i:s.u'));
    $date2sec = strtotime($date2->format('d-m-Y H:i:s.u'));
    //Absolute val of Date 1 in seconds from  (EPOCH Time) - Date 2 in seconds from (EPOCH Time)
    $secdiff = abs($date1sec-$date2sec);
    //Creates variables for the microseconds of date1 and date2
    $micro1 = $date1->format("u");
    $micro2 = $date2->format("u");

    if (($date1sec<$date2sec && $micro1>$micro2)||($date1sec>$date2sec && $micro1<$micro2)){
        $microdiff = abs(1000000 - abs($micro1-$micro2));
        $secdiff = $secdiff - 1;
    } else {
        $microdiff = abs($micro1 - $micro2);
    }

    //Creates the variable that will hold the seconds (?):
    $difference = $secdiff.".".$microdiff;
    return $difference;
}

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

Do you need me to create add and sub?

Solution 5:[5]

i had a similar problem and ended up having to wrap the whole thing

https://gist.github.com/chandeeland/9817516

Solution 6:[6]

For the people only in need to zero-out microseconds (I had to because of database layer) here's the snippet I ended up using:

$format = "Y-m-d H:i:s e";
$now = (new \DateTime())->format($format);
$dateTime = \DateTime::createFromFormat($format, $now);

Note that using $format = 'c', ISO 8601, will not work, as explained here (https://stackoverflow.com/a/10478469/8119317).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jon
Solution 2
Solution 3 Max
Solution 4
Solution 5 David Chan
Solution 6