obtendo formato de data mdY H: i: su de milissegundos

117

Estou tentando obter uma data formatada, incluindo microssegundos de milissegundos.

O único problema é que continuo recebendo 000000

date("m-d-Y H:i:s.u", $milliseconds/1000);

ex. 28/07/2013 11: 26: 14,000000

slik
fonte
6
É estranho que a pergunta solicite a conversão de milissegundos , mas todos respondem como converter microssegundos. Eu sei que você pode converter entre os dois, mas responder à pergunta em vez de copiar e colar o código não relacionado do documento PHP ou de outro lugar seria bom.
Laurent,
Eu sei que já faz um tempo, mas a resposta de bamossza foi a melhor que encontrei aqui
Piyin

Respostas:

122

php.net diz:

Microssegundos (adicionado no PHP 5.2.2). Observe que date()sempre será gerado, 000000já que leva um parâmetro inteiro, ao passo que DateTime::format()oferece suporte a microssegundos se tiver DateTimesido criado com microssegundos.

Portanto, use o mais simples:

$micro_date = microtime();
$date_array = explode(" ",$micro_date);
$date = date("Y-m-d H:i:s",$date_array[1]);
echo "Date: $date:" . $date_array[0]."<br>";

Recomendado e usar a dateTime()classe do referenciado:

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

print $d->format("Y-m-d H:i:s.u"); // note at point on "u"

A nota ué microssegundos (1 segundo = 1000000 µs).

Outro exemplo de php.net :

$d2=new DateTime("2012-07-08 11:14:15.889342");

Referência de dateTime()em php.net

Eu respondi a pergunta tão curta e simplificada para o autor. Consulte para obter mais informações ao autor: obtendo o formato de data mdY H: i: su de milissegundos

Marin Sagovac
fonte
4
Eu geralmente opto pelo segundo formulário porque é mais fácil de ler e entender. Além disso, DateTime é muito mais flexível e robusto do que as funções de data / hora. O tratamento de microssegundos é um caso em questão.
Herbert
Eu concordo com Herbert. @slik, esta É a melhor resposta :)
Marco Sulla
3
@Geo e AlBundy podem ser você tentando isso em uma máquina com php <5.2.2? PHP 5.4.39 executa perfeitamente bem ...
RichardBernards
não seria fácil? data ('mdY H: i: s'). (int) microtime (verdadeiro);
Anant
@Anant, seria bem fácil, de fato. Mas errado. ;) O que você obtém lá é apenas a época em segundos. (Infelizmente, não funcionaria com microtime(false)nenhum deles.)
Sz.
138

Você pode fazer isso prontamente com o formato de entrada U.u.

$now = DateTime::createFromFormat('U.u', microtime(true));
echo $now->format("m-d-Y H:i:s.u");

Isso produz a seguinte saída:

04-13-2015 05:56:22.082300

Na página de manual do PHP para formatos de data:

  • U = segundos desde a época do Unix
  • u = microssegundos

http://php.net/manual/en/function.date.php


Obrigado a giggsey por apontar uma falha em minha resposta original, acrescentando number_format()à linha deve corrigir a caixa do segundo exato. Que pena que não parece mais tão elegante ...

$now = DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', ''));

http://php.net/manual/en/function.number-format.php


Uma nota sobre os fusos horários em resposta ao DaVe.

Normalmente, o createFromFormat()método usará o fuso horário local se nenhum for especificado.

http://php.net/manual/en/datetime.createfromformat.php

No entanto, a técnica descrita aqui é inicializar o objeto DateTime usando microtime()que retorna o número de segundos decorridos desde a época do Unix (01 de janeiro de 1970 00:00:00 GMT).

http://php.net/manual/en/function.microtime.php

Isso significa que o objeto DateTime é inicializado implicitamente em UTC, o que é adequado para tarefas internas do servidor que desejam apenas rastrear o tempo decorrido.

Se precisar exibir a hora para um fuso horário específico, você precisará defini-lo de acordo. No entanto, isso deve ser feito como uma etapa separada após a inicialização ( não usando o terceiro parâmetro de createFromFormat()) por causa das razões discutidas acima.

O setTimeZone()método pode ser usado para cumprir esse requisito.

http://php.net/manual/en/datetime.settimezone.php

Como um exemplo:

$now = DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', ''));
echo $now->format("m-d-Y H:i:s.u") . '<br>';

$local = $now->setTimeZone(new DateTimeZone('Australia/Canberra'));
echo $local->format("m-d-Y H:i:s.u") . '<br>';

Produz a seguinte saída:

10-29-2015 00:40:09.433818
10-29-2015 11:40:09.433818

Observe que se você deseja inserir no mysql, o formato da hora precisa ser:

format("Y-m-d H:i:s.u")
ArchCodeMonkey
fonte
19
Nota: DateTime::createFromFormat('U.u', microtime(true));retornará falso se for microtime(true)executado no segundo exato. Ele retorna '1438616239' em vez de '1438616239.000000'.
giggsey
1
Ótima solução, obrigado. Parece que estou perdendo meu horário local criando $ now do microtime. Qualquer ideia?
dia
1
@daVe Eu adicionei algumas informações sobre fusos horários, espero que seja isso que você estava procurando.
ArchCodeMonkey
1
O number_formaté sempre necessário, mesmo quando não está no segundo exato. Caso contrário, você estará à mercê da precisionopção de configuração do PHP (para "exibição"), que não é alta o suficiente por padrão no PHP 7.0, causando uma perda de precisão (não precisa até o microssegundo).
Teoh Han Hui
1
Sempre role para baixo em StackOverflow
tom10271
15

Aqui está uma abordagem um pouco mais curta. Em vez de trabalhar para criar uma data / hora numérica de alta precisão, converto o valor de microssegundo em uma string, removo o 0e o adiciono ao final da string de data / hora. Posso cortar facilmente o número de decimais ajustando o parâmetro de comprimento da corda; aqui eu uso 4para obter milissegundos, mas você poderia usar 7para obter microssegundos.

$t = explode(" ",microtime());
echo date("m-d-y H:i:s",$t[1]).substr((string)$t[0],1,4);

Para um valor microtime () de 0.98236000 1407400573, retorna 08-07-14 01:08:13.982.

então
fonte
9

Eu estou usando

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

output: 2017-09-05 17:04:57.555036
bamossza
fonte
6
echo date('m-d-Y H:i:s').substr(fmod(microtime(true), 1), 1);

exemplo de saída:

02-06-2019 16:45:03.53811192512512

Se você precisar limitar o número de casas decimais, a linha abaixo (mgutt de crédito) seria uma boa alternativa. (Com o código abaixo, o 6 limita o número de casas decimais a 6.)

echo date('m-d-Y H:i:').sprintf('%09.6f', date('s')+fmod(microtime(true), 1));

exemplo de saída:

02-11-2019 15:33:03.624493
ghbarratt
fonte
Você perdeu a precisão e o zero à esquerda por segundos. Portanto, a versão correta deve ser echo date('m-d-Y H:i:').sprintf('%09.6f', date('s')+fmod(microtime(true), 1));. Explicação do motivo pelo qual precisamos 09: stackoverflow.com/a/28739819/318765
mgutt
Você errou a precisão de novo;)echo date('H:i:s').substr(fmod(microtime(true), 1), 1, 7);
mgutt
Mas cuidado, substr()não arredondar. E, em combinação com round()ele, cortaria os zeros finais: stackoverflow.com/questions/7493305/… Esse é o motivo pelo qual propus sprintf().
mgutt de
@mgutt Quando o primeiro dígito não seria zero? Basicamente, o que é necessário é simplesmente remover o zero que sempre está lá quando se obtém o resto do fmod por 1. A questão pede microssegundos, mas na forma de casas decimais dos segundos. Não há razão para limitar o número de casas decimais. Mais casas decimais são simplesmente melhor precisão.
ghbarratt
@mgutt Eu adicionei sua primeira alternativa sugerida à minha resposta, explicando que seria uma boa maneira de limitar o número de casas decimais, se necessário
ghbarratt
3

Se você deseja formatar uma data como a do JavaScript (new Date()).toISOString()por algum motivo, é assim que você pode fazer em PHP:

$now = microtime(true);
gmdate('Y-m-d\TH:i:s', $now).sprintf('.%03dZ',round(($now-floor($now))*1000));

Saída de amostra:

2016-04-27T18:25:56.696Z

Apenas para provar que subtrair o número inteiro não reduz a precisão da parte decimal:

>>> number_format(123.01234567890123456789,25)
=> "123.0123456789012408307826263"
>>> number_format(123.01234567890123456789-123,25)
=> "0.0123456789012408307826263"

PHP fez em volta das casas decimais, mas arredondado-los da mesma forma em ambos os casos.

mpen
fonte
1
Não. Não use matemática no número de ponto flutuante, é impreciso. Também não perca tempo chamando várias funções. Basta usar substr () para truncar a data formatada para três casas decimais.
LS de
O truncamento de @LS não arredondará o terceiro decimal, o que provavelmente é ainda mais impreciso. Os flutuadores não quebram até que você entre em precisões realmente mínimas; 3 casas decimais devem ser suficientes. Na verdade, não acho que estou alterando a precisão, os flutuadores ficam mais precisos quanto mais perto você chega de 0. Subtrair o número inteiro não deve alterar as casas decimais AFAIK.
MPEN
Sobre o quê date('Y-m-d\TH:i:s', $time / 1000) . sprintf('.%03dZ', substr($time, 10));?
F8ER
@ F8ER Se o seu $timejá estiver em milissegundos, sim, isso funcionaria tecnicamente. Não ameis o substrcorte, mas eu acho que ele iria trabalhar para datas entre 2001 e 2286.
MPEN
Sim, $timeé MS, mas e 2286, quero dizer, por que você pensa assim e como seria possível escapar dela?
F8ER
3

Isso é baseado na resposta do ArchCodeMonkey.

Mas simplificado, se você quiser algo rápido que funcione.

function DateTime_us_utc(){
    return DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', ''));
}
function DateTime_us(){
    $now = DateTime_us_utc();
    return $now->setTimeZone(new DateTimeZone(date_default_timezone_get()));
}

Então para mim então

$now = DateTime_us();
$now->format("m-d-Y H:i:s.u");
John Kearney
fonte
3

Aqui está outro método que considero um pouco mais elegante / simples:

echo date('Y-m-d-H:i:s.').preg_replace("/^.*\./i","", microtime(true));
SDpyro
fonte
1
// Procedural
$fineStamp = date('Y-m-d\TH:i:s') . substr(microtime(), 1, 9);
echo $fineStamp . PHP_EOL;

// Object-oriented (if you must). Still relies on $fineStamp though :-\
$d = new DateTime($fineStamp);
echo $d->format('Y-m-d\TH:i:s.u') . PHP_EOL;
Geo
fonte
1

A partir do PHP 7.1, você pode simplesmente fazer isso:

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

Será exibido como:

04-11-2018 10:54:01.321688
Harveyhase68
fonte
0

A documentação diz o seguinte:

Microssegundos (adicionado no PHP 5.2.2). Observe que date () sempre gerará 000000, pois leva um parâmetro inteiro, enquanto DateTime :: format () oferece suporte a microssegundos.

Ou seja, use DateTime em seu lugar.

Havsmonstret
fonte
6
Isso não funciona! date_format (new DateTime (), 'u') dá zeros: phpfiddle.org/lite/code/ggh-mvz
Jānis Elmeris
Sim, de acordo com a resposta acima (e minhas tentativas) new DateTime()também retornará 0000 para u. Mas se você fornecer um tempo de precisão de microssegundos ao instanciá-lo, ele funcionará bem.
scipilot
@scipilot ok, então como você faz isso?
Geo
@Geo veja a resposta aceita. new DateTime( 'Y-m-d H:i:s.'.$micro);
scipilot
0

Com o PHP 7.0+ agora aqui, você pode fazer o seguinte:

$dateString = substr($millseconds_go_here,0,10);
$drawDate = new \DateTime(Date('Y-m-d H:i',$dateString));
$drawDate->setTimezone(new \DateTimeZone('UTC'));

Isso faz o seguinte em ordem:

  1. Apara os últimos 4 zeros da string para Date()controlar a data.
  2. Usa a data para formatar os milissegundos em uma string de data e hora que DateTime possa entender.
  3. DateTime()pode então permitir que você modifique o fuso horário em que você está, mas certifique-se de que date_default_timezone_set("Timezone");esteja definido antes de usar DateTime()funções e classes.
  4. É uma boa prática usar um construtor em suas classes para garantir que você DateTime()esteja no fuso horário correto quando as classes ou funções forem usadas.
Jamie Ross
fonte
0

se estiver usando Carbon, você pode usar a especificação definida "RFC3339_EXTENDED". ou personalize-o.

Carbon::RFC3339_EXTENDED = 'Y-m-d\TH:i:s.vP';
Aiden Moon
fonte
0

Com base na resposta de @ArchCodeMonkey.

Se você tiver, declare(strict_types=1)você deve lançar o segundo argumento para string

insira a descrição da imagem aqui

SandroMarques
fonte
0

Eu escolhi algumas maneiras diferentes:

1) microtime + sscanf + data:

sscanf(microtime(), '0.%6s00 %s', $usec, $sec);
$date = date('Y-m-d H:i:s.', $sec) . $usec;

Não sei por que microtime () retorna 10 caracteres (0.dddddd00) para a parte de microssegundos, mas talvez alguém possa me dizer?

$start_ts = microtime(true); for($i = 0; $i < 10000000; $i++) { sscanf(microtime(), '0.%6s00 %s', $usec, $sec); $date = date('Y-m-d H:i:s.', $sec) . $usec; } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "22372.335910797 ms" // macOS PHP 5.6.30
string(18) "16772.964000702 ms" // Linux PHP 5.4.16
string(18) "10382.229089737 ms" // Linux PHP 7.3.11 (same linux box as above)

2) DateTime :: createFromFormat + Datetime-> format:

$now = new DateTime('NOW');
$date = $now->format('Y-m-d H:i:s.u');

não funciona no PHP 5.x ...

$start_ts = microtime(true); for($i = 0; $i < 10000000; $i++) { $now = new DateTime('NOW'); $date = $now->format('Y-m-d H:i:s.u'); } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "45801.825046539 ms" // macOS PHP 5.6.30 (ms not working)
string(18) "21180.155038834 ms" // Linux PHP 5.4.16 (ms not working)
string(18) "11879.796028137 ms" // Linux PHP 7.3.11 (same linux box as above)

3) gettimeofday + date:

$time = gettimeofday();
$date = date('Y-m-d H:i:s.', $time['sec']) . $time['usec'];

-

$start_ts = microtime(true); for($i = 0; $i < 10000000; $i++) { $time = gettimeofday(); $date = date('Y-m-d H:i:s.', $time['sec']) . $time['usec']; } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "23706.788063049 ms" // macOS PHP 5.6.30
string(18) "14984.534025192 ms" // Linux PHP 5.4.16
string(18) "7799.1390228271 ms" // Linux PHP 7.3.11 (same linux box as above)

4) microtime + number_format + DateTime :: createFromFormat + DateTime-> format:

$now = DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', ''));
$date = $now->format('Y-m-d H:i:s.u');

-

$start_ts = microtime(true); for($i = 0; $i < 10000000; $i++) { $now = DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', '')); $date = $now->format('Y-m-d H:i:s.u'); } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "83326.496124268 ms" // macOS PHP 5.6.30
string(18) "61982.603788376 ms" // Linux PHP 5.4.16
string(16) "19107.1870327 ms" // Linux PHP 7.3.11 (same linux box as above)

5) microtime + sprintf + DateTime :: createFromFormat + DateTime-> format:

$now = DateTime::createFromFormat('U.u', sprintf('%.6f', microtime(true)));
$date = $now->format('Y-m-d H:i:s.u');

-

$start_ts = microtime(true); for($i = 0; $i < 10000000; $i++) { $now = DateTime::createFromFormat('U.u', sprintf('%.6f', microtime(true))); $date = $now->format('Y-m-d H:i:s.u'); } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "79387.331962585 ms" // macOS PHP 5.6.30
string(18) "60734.437942505 ms" // Linux PHP 5.4.16
string(18) "18594.941139221 ms" // Linux PHP 7.3.11 (same linux box as above)
Fravadona
fonte