如何在PHP中获取当前时间(以毫秒为单位)?


Answers:


506

简短的回答是:

$milliseconds = round(microtime(true) * 1000);

26
@FredrikWendt,我认为您对感到困惑time()microtime(true)另一方面,返回自Unix时期精确到最接近的微秒的当前时间(以秒为单位)(请参阅PHP参考)。如果您在循环中运行上述代码并显示毫秒,实际上非常容易测试。
劳伦特

6
我绝对做到了!:-)
Fredrik Wendt 2012年

9
我喜欢简短的答案。
艾里克·罗伯逊

9
那不应该是microtime(true) / 1000(分裂而不是多重复制)吗?
约旦列夫2014年

18
@JordanLev,它应该是乘法,因为microtime(true)以单位返回Unix时间戳(浮点数)。
laurent

88

使用microtime。此函数返回以空格分隔的字符串。第一部分是秒的小数部分,第二部分是整数部分。传递true以获得号码:

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

如果使用,请当心精度损失microtime(true)

gettimeofday有返回微秒部分作为整数。

var_dump(gettimeofday());
/*
array(4) {
  ["sec"]=>
  int(1283846202)
  ["usec"]=>
  int(891199)
  ["minuteswest"]=>
  int(-60)
  ["dsttime"]=>
  int(1)
}
*/

所以一般来讲microtime()等号1000*time(),对不对?
2010年

我知道,可能有错误,但是错误应该小于1000,对吗?
2010年

@COMer:您正在谈论哪个变体?
kennytm's

microtime(true)1000*time()
COMer 2010年

@COMer:1000*time()不会给您毫秒。microtime(true)返回float精度为14位的。秒部分已经花费了10,因此微秒部分剩下了4位数字。这应该足够了,因为毫秒仅需要3个额外的数字。
kennytm's

46

简短答案:

仅限于64位平台!

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

[ 如果您运行的是64位PHP,则常数PHP_INT_SIZE等于8 ]


长答案:

如果首先要time()以毫秒为单位的等价函数,则必须考虑到time()返回“历元时间”(01/01/1970)以来经过的秒数,因此“历元时间” 以来的毫秒数很大并且不适合32位整数。

PHP中的整数大小可以为32或64位,具体取决于平台。

来自http://php.net/manual/en/language.types.integer.php

整数的大小取决于平台,尽管通常的最大值约为20亿(32位带符号)。64位平台的最大值通常约为9E18,但Windows始终为32位。PHP不支持无符号整数。自PHP 4.4.0和PHP 5.0.5起,可以使用常数PHP_INT_SIZE确定整数大小,并使用常数PHP_INT_MAX确定最大值。

如果您有64位整数,则可以使用以下函数:

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

microtime() 返回自“纪元时间”以来的秒数,精度最高为微秒,两个数字之间用空格分隔,例如...

0.90441300 1409263371

第二个数字是秒(整数),而第一个数字是小数部分。

上面的函数milliseconds()取整数部分乘以1000

1409263371000

然后将小数部分乘以1000并四舍五入到小数点后0位

1409263371904

请注意,$mt[1]和的结果round都强制转换为int。这是必需的,因为它们是floats,并且对其进行操作而没有强制转换将导致函数返回a float

最后,该功能比

round(microtime(true)*1000);

比率为1:10(大约)的结果比正确结果多返回1毫秒。这是由于float类型的精度有限(microtime(true)返回float)。无论如何,如果您仍然喜欢较短的代码,round(microtime(true)*1000);我建议将其转换为int结果。


即使超出了问题的范围,也值得一提的是,如果您的平台支持64位整数,那么您还可以以微秒为单位获取当前时间,而不会引起溢出。

如果事实2^63 - 1(最大有符号整数)除以10^6 * 3600 * 24 * 365(一年中的微秒数)即可得出292471

这与您获得的价值相同

echo (int)( PHP_INT_MAX / ( 1000000 * 3600 * 24 * 365 ) );

换句话说,一个带符号的64位整数有空间存储超过200,000年的时间(以微秒为单位)。

您可能那时

function microseconds() {
    $mt = explode(' ', microtime());
    return ((int)$mt[1]) * 1000000 + ((int)round($mt[0] * 1000000));
}

为什么不只是:`function getMilliEpoch(){$ mt = explode('',microtime()); 返回$ mt [1]。substr($ mt [0],0,5)* 1000; }`
迈克尔

现在有一个用于微时间功能的参数,如果将其设置为true,则返回自1970年1月1日以来的秒数和毫秒数,以float表示的0小时0分钟0秒。这是一个示例:microtime(true)// 1553260455.7242
kukko

@kukko是的,但是由于float类型的精度有限,因此根据microtime(true)计算千分表的数量将导致值略有错误
Paolo

42

正如其他人所述,您可以使用microtime()来获得时间戳的毫秒精度。

从您的评论看来,您似乎希望将其作为高精度的UNIX时间戳记。DateTime.Now.Ticks.NET世界中的某种东西。

您可以使用以下功能来做到这一点:

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);
}

这就是这样做的方式!
tonix 2014年

1
完美..♥。
SRB

它不是返回服务器时间吗?就我而言,我看到在db中存储的时间是我的本地浏览器时间。假设我的服务器时区是EST + 3,浏览器时间是GMT + 6,当我从GMT + 6位置提交表单时,我看到存储的时间是GMT + 6时间等效毫秒。那么,有什么问题呢?:(
Zenith

12

microtime(true)在PHP 5中使用,或在PHP 4中进行以下修改:

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

编写该代码的一种可移植方式是:

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

    return microtime(true);
}

11

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

输出:

2016-11-19 15:12:34.346351


1
这使用相同的时间戳:$t = gettimeofday(); echo date('Y-m-d H:i:s.',$t['sec']) . $t['usec'];
Savvas Radevic

微秒应为零填充:$timeofday=gettimeofday(); echo sprintf("%s.%06d", date('Y-m-d H:i:s', $timeofday['sec']), $timeofday['usec']);
mabi

7

尝试这个:

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"); 
}

6

即使您使用的是32位PHP,它也可以正常工作:

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

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

请注意,这不会给您整数,而是字符串。但是,这在许多情况下都可以正常工作,例如,在为REST请求构建URL时。


如果需要整数,则必须使用64位PHP。

然后,您可以重用上面的代码并将其强制转换为(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

或者,您也可以使用优质的一线服务:

$time_milli = (int) round(microtime(true) * 1000);    // 1491536422147
$time_micro = (int) round(microtime(true) * 1000000); // 1491536422147300

5
$timeparts = explode(" ",microtime());
$currenttime = bcadd(($timeparts[0]*1000),bcmul($timeparts[1],1000));
echo $currenttime;

注意:由于microtime()的改进,该功能需要PHP5,并且还需要bc math模块(由于我们处理大量数字,因此您可以检查phpinfo中是否包含该模块)。

希望这对您有所帮助。


5
$the_date_time = new DateTime($date_string);
$the_date_time_in_ms = ($the_date_time->format('U') * 1000) +
    ($the_date_time->format('u') / 1000);

这真的像在右边填充三个零吗?
Zeeshan

一点也不。它将两个部分都转换为毫秒并给出总和。因此,它比加零更准确。
user3767296

1
尽管此代码段可以解决问题,但提供说明确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。也请尽量不要在代码中加入解释性注释,这会降低代码和解释的可读性!
米哈尔Perłakowski


-2

用这个:

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

再见

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.