3

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
Nick
  • 138,499
  • 22
  • 57
  • 95
Jimmix
  • 5,644
  • 6
  • 44
  • 71

1 Answers1

6

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.

Nick
  • 138,499
  • 22
  • 57
  • 95
  • Just for posterity you can also use `usec`. – Sherif Feb 02 '20 at 00:11
  • @Nick great finding!. Is `microseconds` mentioned anywhere in the manual for `DateInterval`? Where did you find it? Second question how to combine that with other units let say you want an interval of 1 day, 2 hours, 3 minutes and 123456 microseconds - is it possible? – Jimmix Feb 02 '20 at 00:12
  • 1
    Literally just like that. `var_dump(DateInterval::createFromDateString('1 day, 2 hours, 3 minutes and 123456 microseconds'))` TIAS :) – Sherif Feb 02 '20 at 00:18
  • I've updated @Nick's answer to include the documentation about valid Time Formats. – Sherif Feb 02 '20 at 00:24
  • @Sherif actually `1.123456 seconds` won't work, you need to use `1 second 123456 usec` https://3v4l.org/W5AAc – Nick Feb 02 '20 at 00:38
  • @Jimmix it needs to be `'1 day, 2 hours, 3 minutes, 123456 microsecond'` (no `and`) but that will work too: https://3v4l.org/O23gD – Nick Feb 02 '20 at 00:44
  • @Nick Good catch. I could've sworn there was a fractional format somewhere in there. Perhaps I'm wrong. – Sherif Feb 02 '20 at 00:53
  • @Sherif you might be right; I've not come across it but that doesn't mean it's not there – Nick Feb 02 '20 at 00:54