PHP: How to get microseconds

Sometimes it could be necessary to get time with microseconds part. Especially it is good for something like logging when multiple entries are recorded per second and preferably to know how they are spread out.

At first glance everything looked very easy:

print date('Y-m-d H:i:s.u') ;

where u is microseconds.

However it turns out PHP manual has a tiny note which states

Since this [date()] 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().

Which means that u kind of works but in case of calling within date() function the result is always .000000.

So the straight forward solution could be something like this:

print date('Y-m-d H:i:s') . substr((string)microtime(), 1, 8);

But the drawback of the solution above is two calls to the time related functions which potentially may cause some accuracy issues.

Thus even better solution is doing just one call of time function:

list($usec, $sec) = explode(' ', microtime());
print date('Y-m-d H:i:s', $sec) . $usec;

8 Comments so far

  1. Matthew Slyman on May 9th, 2012

    I just wanted to thank you for your illustration of how to use the “list” and “explode” functions together in this tidy manner.

    My post is in relation to this:
    http://aaabit.com/products/microtime-php-class/

  2. Alex on May 9th, 2012

    Matthew,
    Thank you for your feedback and credit.

    Also note that depending on need you may want to explore an option to use mircotime(true) which returns float instead of string.

  3. Matthew Slyman on May 9th, 2012

    Alex,

    Thanks for the pointer regarding microtime(true) – I’ll add this as a comment in the source code!

    My reason for not encouraging that method more generally – and for developing something different – was out of my great care to avoid loss of precision through floating-point arithmetic. There’s a difference in floating-point between:
    – Taking two very large floating-point numbers (with a small difference), and subtracting one from the other; and
    – Taking two very large integer numbers (with a small difference), and subtracting one from the other before converting them into floating-point numbers.

    My concern relates to the fact that we’ve had about 1.26 billion (1.26 x 10^9) seconds since the Unix epoch already. If we say we want 10^6 of precision in microseconds, we’re using 10^15 of information to represent that… So we’re already at the limits of what ordinary floating-point numbers can do without losing precision. As time goes by (with Unix time stamps getting larger), this problem will only get worse – so people using that technique might lose one or two digits of precision, and be dealing with a precision of 10^-4 or 10^-5 seconds instead of 10^-6.
    I think the only easy way to get true microsecond precision then is to use the technique I have outlined.

  4. Alex on May 9th, 2012

    Matthew,

    Thanks for so detailed response. I do agree with you however l like mentioned before – it depends on one’s needs. I think 4-5 decimal digits is often sufficient. But again I totally second that time related library has to be as precise as possible.

    Btw nice catch with the class name since µs is the microsecond symbol.

  5. Sebastian Jurk on October 16th, 2012

    You have an error in the code.

    print date(‘Y-m-d H:i:s’, $sec) . $usec;

    You forgot that $usec is holding a string in the form: 0.00000000 which means you add a zero that doesnt make sense. I use such a function for unixtime with mikrotime added:

    function get_unixusec(){
    list($usec, $sec) = explode(‘ ‘, microtime());
    return date(‘U’, $sec) . substr($usec, -8);
    }

  6. Sebastian Jurk on October 16th, 2012

    I have changed the function a bit so that you can use it with

    get_unixusec() when you want to calculate with it or with get_unixusec(true) when you want to use it in a logfile for better view.

    function get_unixusec($separate_usec = false){
    list($usec, $sec) = explode(‘ ‘, microtime());
    return date(‘U’, $sec) . substr($usec, – 8 – $separate_usec);
    }

  7. Sebastian Jurk on October 16th, 2012

    I noticed another thing… microtime() gives back 8 digits behind the second. Doesnt make sense because microseconds only have 6 digits after the second. So when you want to calculate something should run 250000, that is 0.25 seconds, later then you should have the correct number which is something like:
    1350413363682803 or 1350413363.682854
    The changed function for this:

    function get_unixusec($separate_usec = false){
    list($usec, $sec) = explode(‘ ‘, microtime());
    return date(‘U’, $sec) . substr($usec, – 8 – $separate_usec, 6 $separate_usec);
    }

  8. Alex on October 21st, 2012

    Thank you for your input, Sebastian!

Leave a reply