Como obter tempo atual em milissegundos em PHP?

323

time() está em segundos - há um em milissegundos?

COMer
fonte

Respostas:

506

A resposta curta é:

$milliseconds = round(microtime(true) * 1000);
Laurent
fonte
26
@FredrikWendt, acho que você está confuso time(). microtime(true)por outro lado, retorna o tempo atual em segundos desde que a época do Unix precisa até o microssegundo mais próximo (consulte a referência do PHP). Na verdade, é muito fácil testar se você executa o código acima em um loop e exibe os milissegundos.
laurent
6
Eu absolutamente fiz! :-)
Fredrik Wendt
10
Eu gosto da resposta curta.
precisa
9
Não deveria ser microtime(true) / 1000(divisão em vez de multiplicação múltipla)?
Jordan Lev
18
@JordanLev, deve ser multiplicação porque microtime (true) retorna o carimbo de data e hora do Unix em segundos como um flutuador.
laurent
88

Use microtime. Esta função retorna uma string separada por um espaço. A primeira parte é a parte fracionária de segundos, a segunda parte é a parte integrante. Passe truepara obter como um número:

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

Cuidado com a perda de precisão se você usar microtime(true).

Também há gettimeofdayque retorna a parte de microssegundos como um número inteiro.

var_dump(gettimeofday());
/*
array(4) {
  ["sec"]=>
  int(1283846202)
  ["usec"]=>
  int(891199)
  ["minuteswest"]=>
  int(-60)
  ["dsttime"]=>
  int(1)
}
*/
kennytm
fonte
Então, de maneira geral , microtime()é igual 1000*time(), certo?
Comer
Entendo, pode haver erros, mas o erro deve ser menor que 1000, certo?
Comer
@ COMER: De que variante você está falando?
Kennytm 7/09
microtime(true)e1000*time()
COMer
@ COMER: 1000*time()não lhe dará milissegundos. microtime(true)retorna um floatque possui 14 dígitos de precisão. A parte dos segundos já levava 10, deixando 4 dígitos para a parte dos microssegundos. Isso deve ser suficiente, já que os milissegundos requerem apenas 3 dígitos extras.
Kennytm
46

Resposta curta:

Apenas plataformas de 64 bits!

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

[ Se você estiver executando PHP de 64 bits, a constante será PHP_INT_SIZEigual a8 ]


Resposta longa:

Se você deseja uma função equilibrada time()em milissegundos primeiro, considere que, como time()retorna o número de segundos decorridos desde o "tempo da época" (01/01/1970), o número de milissegundos desde o "tempo da época" é um número grande e não cabe em um número inteiro de 32 bits.

O tamanho de um número inteiro no PHP pode ser de 32 ou 64 bits, dependendo da plataforma.

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

O tamanho de um número inteiro depende da plataforma, embora um valor máximo de cerca de dois bilhões seja o valor usual (com 32 bits assinados). As plataformas de 64 bits geralmente têm um valor máximo de cerca de 9E18, exceto o Windows, que sempre é de 32 bits. O PHP não suporta números inteiros não assinados. O tamanho inteiro pode ser determinado usando a constante PHP_INT_SIZE e o valor máximo usando a constante PHP_INT_MAX desde o PHP 4.4.0 e o PHP 5.0.5.

Se você tiver números inteiros de 64 bits, poderá usar a seguinte função:

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

microtime() retorna o número de segundos desde o "tempo da época" com precisão de até microssegundos com dois números separados por espaço, como ...

0.90441300 1409263371

O segundo número é o segundo (inteiro), enquanto o primeiro é a parte decimal.

A função acima milliseconds()leva a parte inteira multiplicada por1000

1409263371000

em seguida, adiciona a parte decimal multiplicada por 1000e arredondada para 0 casas decimais

1409263371904

Observe que ambos $mt[1]e o resultado de roundsão convertidos para int. Isso é necessário porque eles são se floata operação neles sem conversão resultaria no retorno da função a float.

Finalmente, essa função é um pouco mais precisa do que

round(microtime(true)*1000);

isso com uma proporção de 1:10 (aprox.) retorna 1 milissegundo a mais do que o resultado correto. Isso ocorre devido à precisão limitada do tipo de flutuação ( microtime(true)retorna uma flutuação). De qualquer forma, se você ainda preferir o mais curto round(microtime(true)*1000);, sugiro transmitir into resultado.


Mesmo que esteja além do escopo da pergunta, vale ressaltar que se sua plataforma suportar números inteiros de 64 bits, você também poderá obter o tempo atual em microssegundos sem incorrer no estouro.

Se o fato 2^63 - 1(maior número inteiro assinado) dividido por 10^6 * 3600 * 24 * 365(aproximadamente os microssegundos em um ano) der 292471.

Esse é o mesmo valor que você obtém

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

Em outras palavras, um número inteiro assinado de 64 bits tem espaço para armazenar um período de tempo superior a 200.000 anos medido em microssegundos.

Você pode ter então

function microseconds() {
    $mt = explode(' ', microtime());
    return ((int)$mt[1]) * 1000000 + ((int)round($mt[0] * 1000000));
}
Paolo
fonte
por que não apenas: `function getMilliEpoch () {$ mt = explode ('', microtime ()); retornar $ mt [1]. substr ($ mt [0], 0, 5) * 1000; } `
Michael
Agora, existe um parâmetro para a função microtime, se estiver definido como true, retornará os segundos e milissegundos desde 1º de janeiro de 1970, 0 hora 0 minutos 0 segundos como flutuação. Aqui está um exemplo: microtime (true) // 1553260455.7242
kukko 22/03/19
@kukko sim, mas devido à precisão limitada do tipo float, o cálculo do número de millicesonds de microtime (true) irá resultar em um valor um pouco imprecisa
Paolo
42

Como já foi dito, você pode usar microtime()para obter precisão de milissegundos nos registros de data e hora.

A partir dos seus comentários, você parece desejá-lo como um carimbo de data / hora UNIX de alta precisão. Algo como DateTime.Now.Ticksno mundo .NET.

Você pode usar a seguinte função para fazer isso:

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
fonte
É assim que se faz!
tonix
1
perrrrrrfect .. ♥.
SRB proíbe
Não é retornar o horário do servidor? No meu caso, vejo que o tempo armazenado em db é o horário do meu navegador local. Suponha que meu fuso horário do servidor seja EST + 3 e o horário do meu navegador seja GMT + 6. Enquanto envio um formulário a partir do local GMT + 6, vejo que o tempo armazenado é GMT + 6 milissegundos equivalente ao tempo. Então qual é o problema? :(
Zenith
12

Use microtime(true)no PHP 5 ou a seguinte modificação no PHP 4:

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

Uma maneira portátil de escrever esse código seria:

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

    return microtime(true);
}
Alix Axel
fonte
11

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

resultado:

2016-11-19 15:12:34.346351

mojmir.novak
fonte
1
Ele usa o mesmo carimbo de data / hora:$t = gettimeofday(); echo date('Y-m-d H:i:s.',$t['sec']) . $t['usec'];
Savvas Radevic
microssegundos devem ser preenchidos com zero:$timeofday=gettimeofday(); echo sprintf("%s.%06d", date('Y-m-d H:i:s', $timeofday['sec']), $timeofday['usec']);
mabi
7

tente isto:

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"); 
}
Hồ Lê Thiện Thành
fonte
6

Isso funciona mesmo se você estiver no PHP de 32 bits:

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

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

Observe que isso não fornece números inteiros, mas strings. No entanto, isso funciona bem em muitos casos, por exemplo, ao criar URLs para solicitações REST.


Se você precisar de números inteiros, o PHP de 64 bits é obrigatório.

Então você pode reutilizar o código acima e converter para (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

Ou você pode usar as boas e velhas one-liners:

$time_milli = (int) round(microtime(true) * 1000);    // 1491536422147
$time_micro = (int) round(microtime(true) * 1000000); // 1491536422147300
Gras Double
fonte
5
$timeparts = explode(" ",microtime());
$currenttime = bcadd(($timeparts[0]*1000),bcmul($timeparts[1],1000));
echo $currenttime;

NOTA: O PHP5 é necessário para esta função devido às melhorias com microtime () e o módulo matemático bc também é necessário (como estamos lidando com números grandes, você pode verificar se possui o módulo no phpinfo).

Espero que isso ajude você.

amnippon
fonte
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);
user3767296
fonte
Isso é como preencher três zeros à direita?
Zeeshan
De modo nenhum. Ele converte ambas as partes em milissegundos e fornece a soma. Portanto, é mais preciso do que adicionar zeros.
user3767296
1
Embora esse trecho de código possa resolver a questão, incluir uma explicação realmente ajuda a melhorar a qualidade da sua postagem. Lembre-se de que você está respondendo à pergunta dos leitores no futuro e essas pessoas podem não saber os motivos da sua sugestão de código. Tente também não sobrecarregar seu código com comentários explicativos, pois isso reduz a legibilidade do código e das explicações!
Michał Perłakowski 5/05
1

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
fonte
1
No php <7.1, novos microssegundos DateTime () são sempre 0, veja php.net/manual/en/migration71.incompatible.php .
mabi
-2

Usa isto:

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

Tchau

MIKEEEEE
fonte