412

time() is in seconds - is there one in milliseconds?

laurent
  • 88,262
  • 77
  • 290
  • 428
COMer
  • 5,091
  • 4
  • 22
  • 20

16 Answers16

649

The short answer is:

$milliseconds = floor(microtime(true) * 1000);
laurent
  • 88,262
  • 77
  • 290
  • 428
  • 32
    @FredrikWendt, I think you are confusing with `time()`. `microtime(true)` on the other hand returns the current time in seconds since the Unix epoch accurate to the nearest microsecond (see PHP reference). It's actually very easy to test if you run the above code in a loop and display the milliseconds. – laurent Dec 18 '12 at 10:08
  • 1
    You should take only first 13 digits, otherwise you might get a floating number in ~90%: substr(microtime(true) * 1000, 0, 13); – StanE Jan 28 '14 at 09:16
  • 11
    Shouldn't that be `microtime(true) / 1000` (division instead of mulitplication)? – Jordan Lev Apr 17 '14 at 19:07
  • 28
    @JordanLev, it should be multiplication because microtime(true) returns the Unix timestamp in *seconds* as a float. – laurent Apr 17 '14 at 21:07
  • I really like this solution. Also suitable for microbenchmarking in case it does not have to be too accurate. Helped me a lot finding the bottleneck in my software. – Niklas S. Aug 09 '16 at 08:21
  • 1
    @user25163 You are not absolutely right. If you expect timestamp before "Mon, 31 Oct 1966 14:13:21 GMT" and after "Sat, 20 Nov 2286 17:46:39 GMT" it will be more than 13 digits – HendraWD Nov 09 '16 at 10:32
  • 1
    I do not like the response from this.It's: 1.51196274127E+12 – Vladimir Despotovic Nov 29 '17 at 13:39
  • I don't think you need to round, as `microtime(true)` only returns 4 decimals (PHP v 7.1.16)? – Muundruul Apr 12 '18 at 08:45
  • 1
    Faster and probably precise enough for most people is (int)(microtime(true)*1000) – John Feb 09 '19 at 06:28
  • 1
    Not only is `(int)(microtime(true)*1000)` faster, it's also more correct; with `round` you can end up 0.5ms in the future, with a nasty effect of -1ms time difference somewhere ;-) – rustyx Dec 29 '20 at 22:29
  • I have changed to floor() which indeed prevents the date from being in the future. – laurent May 02 '22 at 14:24
111

Use microtime. This function returns a string separated by a space. The first part is the fractional part of seconds, the second part is the integral part. Pass in true to get as a number:

var_dump(microtime());       // string(21) "0.89115400 1283846202"
var_dump(microtime(true));   // float(1283846202.89)

Beware of precision loss if you use microtime(true).

There is also gettimeofday that returns the microseconds part as an integer.

var_dump(gettimeofday());
/*
array(4) {
  ["sec"]=>
  int(1283846202)
  ["usec"]=>
  int(891199)
  ["minuteswest"]=>
  int(-60)
  ["dsttime"]=>
  int(1)
}
*/
Alessio Cantarella
  • 5,077
  • 3
  • 27
  • 34
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • So generally speaking `microtime()` equals `1000*time()`,right? – COMer Sep 07 '10 at 07:53
  • I see,there can be errors,but the error should be less than `1000`,right? – COMer Sep 07 '10 at 08:01
  • @COMer: Which variant you are talking about? – kennytm Sep 07 '10 at 08:09
  • `microtime(true)` and `1000*time()` – COMer Sep 07 '10 at 08:11
  • @COMer: `1000*time()` won't give you milliseconds. `microtime(true)` returns a `float` which has 14 digits of precision. The seconds part already took 10, so that left 4 digits for the microseconds part. This should be enough since milliseconds only require 3 extra digits. – kennytm Sep 07 '10 at 08:17
  • according to php documentation the `get_as_float` parameter was not available prior to version 5.0.0 – Boris D. Teoharov Mar 21 '13 at 16:59
  • I'm very impressed that you ran all 3 within a microsecond! What server specs are those? :D – Henrik Erlandsson Feb 15 '18 at 12:39
  • When running `var_dump(microtime(true));`, my php (7.1.16) returns 4 decimals: `float(1523522152.2452)`. Possibly the last two digits were 0 in your case and therefore not shown? – Muundruul Apr 12 '18 at 08:39
  • @COMer: Based on other answers in this page, microtime(true) returns the timestamp since the Unix epoch in _seconds_. That said, I don't think this statement is wholly accurate though, since microtime(true) return value can have decimal digits, so it's not exactly integer seconds since the Unix epoch. – nishanthshanmugham Jul 22 '21 at 12:45
63

Short answer:

64 bits platforms only!

function milliseconds() {
    $mt = explode(' ', microtime());
    return intval( $mt[1] * 1E3 ) + intval( round( $mt[0] * 1E3 ) );
}

[ If you are running 64 bits PHP then the constant PHP_INT_SIZE equals to 8 ]


Long answer:

If you want an equilvalent function of time() in milliseconds first you have to consider that as time() returns the number of seconds elapsed since the "epoch time" (01/01/1970), the number of milliseconds since the "epoch time" is a big number and doesn't fit into a 32 bits integer.

The size of an integer in PHP can be 32 or 64 bits depending on platform.

From http://php.net/manual/en/language.types.integer.php

The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). 64-bit platforms usually have a maximum value of about 9E18, except for Windows, which is always 32 bit. PHP does not support unsigned integers. Integer size can be determined using the constant PHP_INT_SIZE, and maximum value using the constant PHP_INT_MAX since PHP 4.4.0 and PHP 5.0.5.

If you have 64 bits integers then you may use the following function:

function milliseconds() {
    $mt = explode(' ', microtime());
    return intval( $mt[1] * 1E3 ) + intval( round( $mt[0] * 1E3 ) );
}

microtime() returns the number of seconds since the "epoch time" with precision up to microseconds with two numbers separated by space, like...

0.90441300 1409263371

The second number is the seconds (integer) while the first one is the decimal part.

The above function milliseconds() takes the integer part multiplied by 1000

1409263371000

then adds the decimal part multiplied by 1000 and rounded to 0 decimals

1409263371904

Note that both $mt[1] and the result of round are casted to int via intval(). This is necessary because they are floats and the operation on them without casting would result in the function returning a float with a loss in precision.

Finally, that function is slightly more precise than

round(microtime(true)*1000);

that with a ratio of 1:10 (approx.) returns 1 more millisecond than the correct result. This is due to the limited precision of the float type (microtime(true) returns a float). Anyway if you still prefer the shorter round(microtime(true)*1000); I would suggest casting to int the result.


Even if it's beyond the scope of the question it's worth mentioning that if your platform supports 64 bits integers then you can also get the current time in microseconds without incurring in overflow.

If fact 2^63 - 1 (biggest signed integer) divided by 10^6 * 3600 * 24 * 365 (approximately the microseconds in one year) gives 292471.

That's the same value you get with

echo intdiv( PHP_INT_MAX, 1E6 * 3600 * 24 * 365 );

In other words, a signed 64 bits integer have room to store a timespan of over 200,000 years measured in microseconds.

You may have then

function microseconds() {
    $mt = explode(' ', microtime());
    return intval( $mt[1] * 1E6 ) + intval( round( $mt[0] * 1E6 ) );
}
Paolo
  • 15,233
  • 27
  • 70
  • 91
  • why not just: ` function getMilliEpoch(){ $mt = explode(' ', microtime()); return $mt[1] . substr($mt[0], 0, 5) * 1000; }` – Michael May 14 '17 at 08:22
  • 1
    Now there is a parameter for microtime function, if it is set to true, it's return the seconds and milliseconds since 1st of january in 1970, 0 hour 0 minutes 0 seconds as float. Here is an example: microtime(true) // 1553260455.7242 – kukko Mar 22 '19 at 13:17
  • @kukko yes, but due to **limited precision** of the float type, calculating the number of millicesonds from microtime(true) will result in a **slightly inaccurate value** – Paolo Mar 23 '19 at 10:27
49

As other have stated, you can use microtime() to get millisecond precision on timestamps.

From your comments, you seem to want it as a high-precision UNIX Timestamp. Something like DateTime.Now.Ticks in the .NET world.

You may use the following function to do so:

function millitime() {
  $microtime = microtime();
  $comps = explode(' ', $microtime);

  // Note: Using a string here to prevent loss of precision
  // in case of "overflow" (PHP converts it to a double)
  return sprintf('%d%03d', $comps[1], $comps[0] * 1000);
}
Andrew Moore
  • 93,497
  • 30
  • 163
  • 175
  • Is not it return the server time? In my case I see the stored time in db is my local browser time. Suppose, my sever timezone is EST+3 and my browser time is GMT+6, While I submit a form from GMT+6 location, I see the stored time is GMT+6 time equivalent millisecond. So, What is the problem? :( – Zenith Sep 16 '18 at 14:04
29

Shortest version of string variant (32-bit compatibile):

$milliseconds = date_create()->format('Uv');
Milan Majer
  • 594
  • 6
  • 8
16

echo date('Y-m-d H:i:s.') . gettimeofday()['usec'];

output:

2016-11-19 15:12:34.346351

Xorifelse
  • 7,878
  • 1
  • 27
  • 38
mojmir.novak
  • 2,920
  • 3
  • 24
  • 32
  • 1
    This uses the same timestamp: `$t = gettimeofday(); echo date('Y-m-d H:i:s.',$t['sec']) . $t['usec'];` – Savvas Radevic Oct 02 '17 at 10:04
  • 2
    microseconds should be zero padded: `$timeofday=gettimeofday(); echo sprintf("%s.%06d", date('Y-m-d H:i:s', $timeofday['sec']), $timeofday['usec']);` – mabi May 20 '20 at 05:26
14

Use microtime(true) in PHP 5, or the following modification in PHP 4:

array_sum(explode(' ', microtime()));

A portable way to write that code would be:

function getMicrotime()
{
    if (version_compare(PHP_VERSION, '5.0.0', '<'))
    {
        return array_sum(explode(' ', microtime()));
    }

    return microtime(true);
}
Alix Axel
  • 151,645
  • 95
  • 393
  • 500
10

This works even if you are on 32-bit PHP:

list($msec, $sec) = explode(' ', microtime());

$time_milli = $sec.substr($msec, 2, 3); // '1491536422147'
$time_micro = $sec.substr($msec, 2, 6); // '1491536422147300'

Note this doesn't give you integers, but strings. However this works fine in many cases, for example when building URLs for REST requests.


If you need integers, 64-bit PHP is mandatory.

Then you can reuse the above code and cast to (int):

list($msec, $sec) = explode(' ', microtime());

// these parentheses are mandatory otherwise the precedence is wrong!
//                  ↓                        ↓
$time_milli = (int) ($sec.substr($msec, 2, 3)); // 1491536422147
$time_micro = (int) ($sec.substr($msec, 2, 6)); // 1491536422147300

Or you can use the good ol' one-liners:

$time_milli = (int) round(microtime(true) * 1000);    // 1491536422147
$time_micro = (int) round(microtime(true) * 1000000); // 1491536422147300
Gras Double
  • 15,901
  • 8
  • 56
  • 54
8

try this:

public function getTimeToMicroseconds() {
    $t = microtime(true);
    $micro = sprintf("%06d", ($t - floor($t)) * 1000000);
    $d = new DateTime(date('Y-m-d H:i:s.' . $micro, $t));

    return $d->format("Y-m-d H:i:s.u"); 
}
8

PHP 5.2.2 <

$d = new DateTime();
echo $d->format("Y-m-d H:i:s.u"); // u : Microseconds

PHP 7.0.0 < 7.1

$d = new DateTime();
echo $d->format("Y-m-d H:i:s.v"); // v : Milliseconds 
Sadee
  • 3,010
  • 35
  • 36
  • 1
    In php <7.1 new DateTime() microseconds are always 0 see https://www.php.net/manual/en/migration71.incompatible.php. – mabi May 20 '20 at 05:36
6
$timeparts = explode(" ",microtime());
$currenttime = bcadd(($timeparts[0]*1000),bcmul($timeparts[1],1000));
echo $currenttime;

NOTE: PHP5 is required for this function due to the improvements with microtime() and the bc math module is also required (as we’re dealing with large numbers, you can check if you have the module in phpinfo).

Hope this help you.

amnippon
  • 311
  • 4
  • 10
6
$the_date_time = new DateTime($date_string);
$the_date_time_in_ms = ($the_date_time->format('U') * 1000) +
    ($the_date_time->format('u') / 1000);
miken32
  • 42,008
  • 16
  • 111
  • 154
user3767296
  • 239
  • 4
  • 5
  • Is that actually like padding three zeroes to the right? – Zeeshan Aug 12 '15 at 04:20
  • Not at all. It convert both part to milliseconds and give the sum. So it is more accurate than add zeros. – user3767296 Aug 13 '15 at 05:53
  • 1
    While this code snippet may solve the question, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations! – Michał Perłakowski May 05 '16 at 20:11
0

This is my implementation, should work on 32bit as well.

function mstime(){
    $mstime = explode(' ',microtime());
    return $mstime[1].''.(int)($mstime[0]*1000);
}
Oliver M Grech
  • 3,071
  • 1
  • 21
  • 36
0

If you want to see real microseconds, you will need to change the precision setting in php.ini to 16.

After that, microsecond(true) gave me the output of 1631882476.298437.

So I thought that I need to divide the remainder (298437) with 1000, but in fact, the remainder is 0.298437 of a second. So I need to multiply that by 1000 to get the correct result.

    function get_milliseconds()
    {
        $timestamp = microtime(true);
        return (int)(($timestamp - (int)$timestamp) * 1000);
    }
domaci_a_nas
  • 220
  • 2
  • 11
0

I personaly use this:

public static function formatMicrotimestamp(DateTimeInterface $dateTime): int
{
    return (int) substr($dateTime->format('Uu'), 0, 13);
}
Wolly Wombat
  • 99
  • 1
  • 1
  • 9
-4

Use this:

function get_millis(){
  list($usec, $sec) = explode(' ', microtime());
  return (int) ((int) $sec * 1000 + ((float) $usec * 1000));
}

Bye