23

I was measuring some curl requests and I used microtime(true). The example output would be 3.1745569706

This is 3.1745569706 seconds. I want to convert that to a somewhat more readable format, let's say 00:00:03:17455 (HOURS:MINUTES:SECONDS:MILLISECONDS)

$maxWaitTime = '3.1745569706';
echo gmdate("H:i:s.u", $maxWaitTime);

// which returns
00:00:01.000000

echo date("H:i:s.u" , $maxWaitTime)
// which returns
18:00:01.000000

That looks wrong. I'm not quite sure what I'm missing here.

How do I convert microtime() to HH:MM:SS:UU ?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
ProDraz
  • 1,283
  • 6
  • 22
  • 43

3 Answers3

28

From the PHP.net article on date() which is similar to gmdate(), except that the time is returned in GMT:

Since this function only accepts integer timestamps the u format character is only useful when using the date_format() function with user based timestamps created with date_create().

Use something like this instead:

list($usec, $sec) = explode(' ', microtime()); //split the microtime on space
                                               //with two tokens $usec and $sec

$usec = str_replace("0.", ".", $usec);     //remove the leading '0.' from usec

print date('H:i:s', $sec) . $usec;       //appends the decimal portion of seconds

Which prints: 00:00:03.1745569706

If you want you can use round() to round the $usec var even more.

If you use microtime(true) use this instead:

list($sec, $usec) = explode('.', microtime(true)); //split the microtime on .
Sloganho
  • 2,041
  • 3
  • 16
  • 20
edwardmp
  • 6,339
  • 5
  • 50
  • 77
  • What if you replace the predefined variable with microtime() (check my updated reply) – edwardmp May 29 '13 at 23:24
  • I get 18:24:570.94270700, I'm soo confused, but I believe it's getting server time or something... – ProDraz May 29 '13 at 23:25
  • I'm not sure, but I suspect something is wrong on your server. – edwardmp May 29 '13 at 23:25
  • 1
    If you have to use `microtime(true)`, then the output format is a float number (obviously with a dot delimiter). You should therefore use `list($sec, $usec) = explode('.', $maxWaitTime);` instead. – Yako Aug 17 '13 at 09:56
6
<?php

function format_period($seconds_input)
{
  $hours = (int)($minutes = (int)($seconds = (int)($milliseconds = (int)($seconds_input * 1000)) / 1000) / 60) / 60;
  return $hours.':'.($minutes%60).':'.($seconds%60).(($milliseconds===0)?'':'.'.rtrim($milliseconds%1000, '0'));
}

echo format_period(3.1745569706);

OUTPUT

0:0:3.174
Yogus
  • 2,307
  • 5
  • 20
  • 38
  • Thanks for the function helped me a lot - it needs to add (ini) before $hours i.e. 'return (ini)$hours' etc. - was pulling my hair thinking that my code was wrong - until looked over your function – Ash501 Nov 21 '14 at 05:10
  • @Ash501 you should have added `(ini)` before `$hours`? What exactly is this `(ini)` type converting to? And either with or without (int) at the return part it shouts the same result. – khael Nov 21 '14 at 05:36
  • @khael - the (ini) prevents hours to be shown with decimals. Try the function with microtime 121.87023377419 and you'll see what i mean. – Ash501 Nov 21 '14 at 17:11
  • @Ash501 , to me `(ini)` shouts an error, maybe I am just missing the right php version, maybe it is `(int)`, but in that case won't have the behaviour you described. – khael Nov 21 '14 at 17:14
  • @khael, did you try the function with the above number? -It breaks the readable 00:00:00.000 format - Im using php 5.5. – Ash501 Nov 21 '14 at 17:31
  • @Ash501 this is getting tiring, yes, I tried it, and as far as I know the syntax `(something)` is a type conversion, therefore `(ini)` should, by my knowledge, try to convert whatever is after it to the type `ini`. And anyway, with the description provided the function seems to work just fine, needed only some minor adjustments. – khael Nov 21 '14 at 17:34
0

Assuming one really cares about microseconds, which is admittedly rare, then one should not use any representation that involves floats.

Instead use gettimeofday() which will return an associative array that contains the seconds and microseconds as integers.

$g1 = gettimeofday();
# execute your process here
$g2 = gettimeofday();

$borrow  = $g2['usec'] < $g1['usec'] ;
$seconds = $g2['sec'] - $g1['sec'] - $borrow ;
$micros  = $borrow*1000000 + $g2['usec'] - $g1['usec'] ;
$delta   = gmdate( 'H:i:s.', $seconds ).sprintf( '%06d', $micros );
Jeff
  • 2,095
  • 25
  • 18
  • too bad the overhead of calling gettimeofday() effectively wipes out any theoretical gain in accuracy :-( – Jeff Jun 02 '18 at 02:51
  • Apparently gettimeofday() is also potentially subject to wild swings if the clock gets updated by ntp (or otherwise changes). – Jeff Jun 02 '18 at 14:55