Search code examples
phpdatetimeprecisionintervalsdateinterval

PHP DateInterval create split second (microsecond or milisecond) interval


How to create split second DateInterval in PHP? For example:

0.123456 sec

?

interval_spec of DateInterval::__construct

does not have F nor f similarly to DateInterval::format that supports split seconds.

Relative format listing of DateInterval::createFromDateString also does not mention any fraction of a sec.

But the DateInterval class properties listing shows:

f Number of microseconds, as a fraction of a second.

I was able to get DateInterval with a split second by using the DateTime::diff of two DateTimes with a split seconds

example:

$formatStr = 'Y-m-d H:i:s.u';
$dateTimeStr = '2000-01-01 00:00:00.0';
$timeZone = new \DateTimeZone('UTC'); 
$timerDateTimeStart = \DateTimeImmutable::createFromFormat($formatStr, $dateTimeStr, $timeZone);

$formatStr = 'Y-m-d H:i:s.u';
$dateTimeStr = '2000-01-01 00:00:00.123456';
$timeZone = new \DateTimeZone('UTC');
$timerDateTimeEnd = \DateTimeImmutable::createFromFormat($formatStr, $dateTimeStr, $timeZone);

$timerDiff = $timerDateTimeStart->diff($timerDateTimeEnd);
$intervalStr = $timerDiff->format('%Y-%M-%D %H:%I:%S.%f');
echo 'Interval (yyyy-mm-dd hh:mm:ss.sfract): ' . $intervalStr;

gives:

Interval (yyyy-mm-dd hh:mm:ss.sfract): 00-00-00 00:00:00.123456

since DateTime supports the split second time_format in its constructor and DateTime::createFromFormat understands

u Microseconds (up to six digits) Example: 45, 654321

BTW: don't you think that u in case of working with the DateTime and F or f in case of DateInterval has a potential for making your day a little bit less boring?

One of my workaround could be to create two DateTime with a split second precision and then diff to get the DateInterval with the same split second precision but I would like to get the same result with just the DateInterval.

Do you know how to create DateInterval having 0.123456 sec by using just the DateInterval?

Solution based on the accepted answer:

$dateInterval = DateInterval::createFromDateString("1 day, 2 hours, 3 minutes, 1 second, 123456 microsecond");
$intervalStr = $dateInterval->format('%D %H:%I:%S.%F');
echo 'Interval (dd hh:mm:ss.sfract): ' . $intervalStr . PHP_EOL;

gives:

Interval (dd hh:mm:ss.sfract): 01 02:03:01.123456

Solution

  • There is a way to do this using DateInterval::createFromDateString:

    $di = DateInterval::createFromDateString('123456 microseconds');
    var_dump($di);
    

    Output:

    object(DateInterval)#1 (16) {
      ["y"]=>
      int(0)
      ["m"]=>
      int(0)
      ["d"]=>
      int(0)
      ["h"]=>
      int(0)
      ["i"]=>
      int(0)
      ["s"]=>
      int(0)
      ["f"]=>
      float(0.123456)
      ["weekday"]=>
      int(0)
      ["weekday_behavior"]=>
      int(0)
      ["first_last_day_of"]=>
      int(0)
      ["invert"]=>
      int(0)
      ["days"]=>
      bool(false)
      ["special_type"]=>
      int(0)
      ["special_amount"]=>
      int(0)
      ["have_weekday_relative"]=>
      int(0)
      ["have_special_relative"]=>
      int(0)
    }
    

    Demo on 3v4l.org

    From the manual:

    time

    A date with relative parts. Specifically, the relative formats supported by the parser used for strtotime() and DateTime will be used to construct the DateInterval.