obteniendo el formato de fecha mdY H: i: su de milisegundos

117

Estoy tratando de obtener una fecha formateada, incluidos los microsegundos de milisegundos.

El único problema es que sigo recibiendo 000000

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

ex. 28/07/2013 11: 26: 14.000000

slik
fuente
6
Es extraño que la pregunta pida convertir milisegundos , pero todos responden cómo convertir microsegundos. Sé que puede convertir entre ambos, pero en realidad responder a la pregunta en lugar de copiar y pegar código no relacionado del documento PHP o de otro lugar sería bueno.
Laurent
Sé que ha pasado un tiempo, pero la respuesta de bamossza fue la mejor que encontré aquí
Piyin

Respuestas:

122

php.net dice:

Microsegundos (agregado en PHP 5.2.2). Tenga en cuenta que date()siempre generará, 000000ya que toma un parámetro entero, mientras DateTime::format()que admite microsegundos si DateTimese creó con microsegundos.

Así que use tan simple:

$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>";

dateTime()Clase recomendada y de uso de la referencia:

$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"

La nota ues microsegundos (1 segundo = 1000000 µs).

Otro ejemplo de php.net :

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

Referencia de dateTime()en php.net

Respondí una pregunta tan breve y simplificada al autor. Para obtener más información, consulte al autor: obteniendo el formato de fecha mdY H: i: su de milisegundos

Marin Sagovac
fuente
4
Por lo general, opto por el segundo formulario, ya que es más fácil de leer y comprender. Además, DateTime es mucho más flexible y robusto que las funciones de fecha / hora. El manejo de microsegundos es un buen ejemplo.
Herbert
3
@Geo y AlBundy, ¿podría ser que esté probando esto en una máquina con php <5.2.2? PHP 5.4.39 ejecuta esto perfectamente bien ...
RichardBernards
¿No sería esto fácil? fecha ('mdY H: i: s'). (int) microtime (verdadero);
Anant
@Anant, sería bastante fácil, de hecho. Pero mal. ;) Lo que obtienes allí es solo la época en segundos. (Desafortunadamente, tampoco funcionaría con microtime(false)ninguno).
Sz.
Este código no funciona correctamente en todas las configuraciones regionales. Algunos países como Alemania escriben "0,1234" o "0.1234" en lugar de ".1234", por lo que su código me da el siguiente resultado: 2012-07-08 11:14:15.0.889342
Daniel Marschall
138

Puede hacer esto fácilmente con el formato de entrada U.u.

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

Esto produce la siguiente salida:

04-13-2015 05:56:22.082300

Desde la página del manual de PHP para formatos de fecha:

  • U = Segundos desde la época de Unix
  • u = Microsegundos

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


Gracias a giggsey por señalar un defecto en mi respuesta original, agregar number_format()a la línea debería corregir el caso del segundo exacto. Lástima que ya no se sienta tan elegante ...

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

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


Una nota sobre las zonas horarias en respuesta a DaVe.

Normalmente el createFromFormat() método utilizará la zona horaria local si no se especifica una.

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

Sin embargo, la técnica descrita aquí es inicializar el objeto DateTime usando microtime() cual devuelve el número de segundos transcurridos desde la época de Unix (01 de enero de 1970 00:00:00 GMT).

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

Esto significa que el objeto DateTime se inicializa implícitamente en UTC, lo que está bien para las tareas internas del servidor que solo desean realizar un seguimiento del tiempo transcurrido.

Si necesita mostrar la hora de una zona horaria en particular, debe configurarla en consecuencia. Sin embargo, esto debe hacerse como un paso separado después de la inicialización ( sin usar el tercer parámetro decreateFromFormat() ) debido a las razones discutidas anteriormente.

los setTimeZone() método se puede utilizar para cumplir con este requisito.

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

Como ejemplo:

$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>';

Produce la siguiente salida:

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

Tenga en cuenta que si desea ingresar en mysql, el formato de hora debe ser:

format("Y-m-d H:i:s.u")
ArchCodeMonkey
fuente
19
Nota: DateTime::createFromFormat('U.u', microtime(true));devolverá falso si se microtime(true)ejecuta en el segundo exacto. Devuelve '1438616239' en lugar de '1438616239.000000'.
giggsey
1
Gran solución, gracias. Parece que estoy perdiendo mi hora local creando $ ahora a partir de microtiempo. ¿Alguna idea?
Viernes
1
@daVe He agregado información sobre zonas horarias, espero que eso sea lo que buscabas.
ArchCodeMonkey
1
El number_formatsiempre es necesario, incluso cuando no está en el segundo exacto. De lo contrario, está a merced de la precisionopción de configuración de PHP (para "mostrar"), que no es lo suficientemente alta por defecto a partir de PHP 7.0, lo que provoca una pérdida de precisión (no precisa hasta el microsegundo).
Teoh Han Hui
1
Siempre desplácese hacia abajo en StackOverflow
tom10271
15

Aquí hay un enfoque un poco más corto. En lugar de trabajar para crear una fecha / hora numérica de alta precisión, convierto el valor del microsegundo en una cadena, elimino el 0y lo agrego al final de la cadena de fecha / hora. Puedo recortar fácilmente el número de decimales ajustando el parámetro de longitud de la cadena; aquí utilizo 4para obtener milisegundos, pero podrías usar 7para obtener microsegundos.

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

Para un valor de microtime () de 0.98236000 1407400573, esto regresa 08-07-14 01:08:13.982.

thotso
fuente
9

Estoy usando

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

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

ejemplo de salida:

02-06-2019 16:45:03.53811192512512

Si necesita limitar el número de posiciones decimales, la siguiente línea (mgutt de crédito) sería una buena alternativa. (Con el siguiente código, el 6 limita el número de posiciones decimales a 6.)

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

ejemplo de salida:

02-11-2019 15:33:03.624493
ghbarratt
fuente
Perdiste la precisión y el cero inicial durante unos segundos. Entonces la versión correcta debería ser echo date('m-d-Y H:i:').sprintf('%09.6f', date('s')+fmod(microtime(true), 1));. Explicación por qué necesitamos 09: stackoverflow.com/a/28739819/318765
mgutt
Te perdiste la precisión de nuevo;)echo date('H:i:s').substr(fmod(microtime(true), 1), 1, 7);
mgutt
Pero ojo, substr()no se redondea. Y en combinación con round()él cortaría los ceros finales: stackoverflow.com/questions/7493305/… Esa es la razón por la que propuse sprintf().
mgutt
@mgutt ¿Cuándo el primer dígito no sería cero? Básicamente, lo que se necesita es simplemente eliminar el cero que siempre está ahí cuando se obtiene el resto de fmod en 1. La pregunta pide microsegundos pero en forma de lugares decimales de los segundos. No hay razón para limitar el número de decimales. Más lugares decimales es simplemente mejor precisión.
ghbarratt
@mgutt Agregué su primera alternativa sugerida a mi respuesta, explicando que esa sería una buena manera de limitar el número de lugares decimales si es necesario
ghbarratt
3

Si desea formatear una fecha como la de JavaScript (new Date()).toISOString()por alguna razón, así es como puede hacerlo en PHP:

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

Salida de muestra:

2016-04-27T18:25:56.696Z

Solo para demostrar que restar el número entero no reduce la precisión de la parte decimal:

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

PHP hizo alrededor de las cifras decimales, redondeada pero ellos de la misma manera en ambos casos.

mpen
fuente
1
No. No use matemáticas en el número de punto flotante, es inexacto. Además, no pierda el tiempo llamando a varias funciones. Simplemente use substr () para truncar la fecha formateada a tres lugares decimales.
LS
@LS Truncating no redondeará el tercer decimal, que probablemente sea aún más inexacto. Los flotadores no se rompen hasta que no consigues precisiones muy pequeñas; 3 lugares decimales deberían estar bien. En realidad, no creo que esté alterando la precisión en absoluto, los flotadores se vuelven más precisos cuanto más te acercas a 0. Restar el número entero no debería alterar los lugares decimales AFAIK.
mpen
¿Qué hay de date('Y-m-d\TH:i:s', $time / 1000) . sprintf('.%03dZ', substr($time, 10));?
F8ER
@ F8ER Si $timeya está en milisegundos, sí, eso técnicamente funcionaría. No me encanta el substrtruco, pero supongo que funcionaría para fechas entre 2001 y 2286.
mpen
Sí, $timees EM, pero ¿qué pasa? 2286Quiero decir, ¿por qué creo eso y cómo sería posible escapar de ella?
F8ER
3

Esto se basa en la respuesta de ArchCodeMonkey.

Pero simplificado, si solo quieres 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()));
}

Entonces para mi entonces

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

Aquí hay otro método que encuentro un poco más elegante / simple:

echo date('Y-m-d-H:i:s.').preg_replace("/^.*\./i","", microtime(true));
SDpyro
fuente
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
fuente
1

A partir de PHP 7.1, simplemente puede hacer esto:

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

Se mostrará como:

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

La documentación dice lo siguiente:

Microsegundos (agregado en PHP 5.2.2). Tenga en cuenta que date () siempre generará 000000 ya que toma un parámetro entero, mientras que DateTime :: format () admite microsegundos.

Es decir, use DateTime en su lugar.

Havsmonstret
fuente
6
¡Esto no funciona! date_format (new DateTime (), 'u') da ceros: phpfiddle.org/lite/code/ggh-mvz
Jānis Elmeris
Sí, según la respuesta anterior (y mis pruebas) new DateTime()también devolverán 0000 para u. Pero si le proporciona un tiempo de precisión de microsegundos al crear una instancia, funciona bien.
scipilot
@scipilot ok, ¿cómo lo haces?
Geo
@Geo vea la respuesta aceptada. new DateTime( 'Y-m-d H:i:s.'.$micro);
scipilot
0

Con PHP 7.0+ ahora aquí puede hacer lo siguiente:

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

Esto hace lo siguiente en orden:

  1. Recorta los últimos 4 ceros de la cuerda para Date() poder manejar la fecha.
  2. Utiliza la fecha para formatear los milisegundos en una cadena de fecha y hora que DateTime pueda comprender.
  3. DateTime()luego puede permitirle modificar la zona horaria en la que se encuentra, pero asegúrese de que date_default_timezone_set("Timezone");esté configurado antes de usarDateTime() funciones y clases.
  4. Es una buena práctica usar un constructor en tus clases para asegurarte de que estás en la zona horaria correcta cuando DateTime()se usan clases o funciones.
Jamie Ross
fuente
0

si está utilizando Carbon, puede utilizar la especificación definida "RFC3339_EXTENDED". o personalizarlo.

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

Basado en la respuesta de @ArchCodeMonkey.

Si tiene declare(strict_types=1), debe lanzar el segundo argumento a la cadena

ingrese la descripción de la imagen aquí

SandroMarques
fuente
0

Me lancé a la banca de diferentes maneras:

1) microtime + sscanf + fecha:

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

No estoy seguro de por qué microtime () devuelve 10 caracteres (0.dddddd00) para la parte de microsegundos, pero tal vez alguien pueda decirme.

$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-> formato:

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

no funciona en 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-> formato:

$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-> formato:

$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
fuente