¿Cómo obtener la hora actual en milisegundos en PHP?


Respuestas:


506

La respuesta corta es:

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

26
@FredrikWendt, creo que te confunde time(). microtime(true)Por otro lado, devuelve el tiempo actual en segundos desde la época de Unix con precisión al microsegundo más cercano (consulte la referencia de PHP). En realidad, es muy fácil probar si ejecuta el código anterior en un bucle y muestra los milisegundos.
Laurent

66
¡Lo hice absolutamente! :-)
Fredrik Wendt

10
Me gusta la respuesta corta.
Erick Robertson

99
¿No debería ser eso microtime(true) / 1000(división en lugar de multiplicación)?
Jordan Lev

18
@JordanLev, debería ser una multiplicación porque microtime (verdadero) devuelve la marca de tiempo de Unix en segundos como flotante.
Laurent

88

Uso microtime. Esta función devuelve una cadena separada por un espacio. La primera parte es la parte fraccionaria de segundos, la segunda parte es la parte integral. Pase truepara obtener un número:

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

Tenga cuidado con la pérdida de precisión si usa microtime(true) .

También hay gettimeofdayque devuelve la parte de microsegundos como un entero.

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

Entonces, en términos generales , microtime()es igual 1000*time(), ¿verdad?
Viene el

Ya veo, puede haber errores, pero el error debería ser menor que 1000, ¿verdad?
Viene el

@COMer: ¿De qué variante estás hablando?
kennytm

microtime(true)y1000*time()
COMer

@COMer: 1000*time()no te dará milisegundos. microtime(true)devuelve un floatque tiene 14 dígitos de precisión. La parte de segundos ya tomó 10, por lo que dejó 4 dígitos para la parte de microsegundos. Esto debería ser suficiente ya que los milisegundos solo requieren 3 dígitos adicionales.
kennytm

46

Respuesta corta:

¡Solo plataformas de 64 bits!

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

[ Si está ejecutando PHP de 64 bits, entonces la constante PHP_INT_SIZEes igual a8 ]


Respuesta larga:

Si desea una función equivalente time()en milisegundos primero, debe tener en cuenta que, como time()devuelve el número de segundos transcurridos desde el "tiempo de época" (01/01/1970), el número de milisegundos desde el "tiempo de época" es un número grande y no cabe en un entero de 32 bits.

El tamaño de un número entero en PHP puede ser de 32 o 64 bits, dependiendo de la plataforma.

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

El tamaño de un número entero depende de la plataforma, aunque un valor máximo de aproximadamente dos mil millones es el valor habitual (32 bits con signo). Las plataformas de 64 bits generalmente tienen un valor máximo de aproximadamente 9E18, a excepción de Windows, que siempre es de 32 bits. PHP no admite enteros sin signo. El tamaño entero se puede determinar usando la constante PHP_INT_SIZE, y el valor máximo usando la constante PHP_INT_MAX desde PHP 4.4.0 y PHP 5.0.5.

Si tiene enteros de 64 bits, puede usar la siguiente función:

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

microtime() devuelve el número de segundos desde el "tiempo de época" con precisión hasta microsegundos con dos números separados por espacio, como ...

0.90441300 1409263371

El segundo número son los segundos (entero) mientras que el primero es la parte decimal.

La función anterior milliseconds()toma la parte entera multiplicada por1000

1409263371000

luego agrega la parte decimal multiplicada por 1000y redondeada a 0 decimales

1409263371904

Tenga en cuenta que ambos $mt[1]y el resultado de roundse lanzan a int. Esto es necesario porque son floatsy la operación en ellos sin conversión resultaría en que la función devuelva a float.

Finalmente, esa función es un poco más precisa que

round(microtime(true)*1000);

que con una relación de 1:10 (aprox.) devuelve 1 milisegundo más que el resultado correcto. Esto se debe a la precisión limitada del tipo flotante ( microtime(true)devuelve un flotante). De todos modos, si aún prefieres el más corto, round(microtime(true)*1000);te sugiero que arrojes intel resultado.


Incluso si está fuera del alcance de la pregunta, vale la pena mencionar que si su plataforma admite enteros de 64 bits, también puede obtener la hora actual en microsegundos sin incurrir en un desbordamiento.

Si el hecho 2^63 - 1(mayor entero con signo) dividido entre 10^6 * 3600 * 24 * 365(aproximadamente los microsegundos en un año) da 292471.

Ese es el mismo valor que obtienes con

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

En otras palabras, un entero de 64 bits con signo tiene espacio para almacenar un intervalo de tiempo de más de 200,000 años medido en microsegundos.

Puede que tengas entonces

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

por qué no solo: `function getMilliEpoch () {$ mt = explotar ('', microtime ()); devuelve $ mt [1]. substr ($ mt [0], 0, 5) * 1000; } `
Michael

Ahora hay un parámetro para la función de microtiempo, si se establece en verdadero, devuelve los segundos y milisegundos desde el 1 de enero de 1970, 0 horas 0 minutos 0 segundos como flotante. Aquí hay un ejemplo: microtime (verdadero) // 1553260455.7242
kukko

@kukko sí, pero debido a la precisión limitada del tipo de flotación, calcular el número de milisegundos de microtiempo (verdadero) dará como resultado un valor ligeramente inexacto
Paolo

42

Como han dicho otros, puede usar microtime()para obtener una precisión de milisegundos en las marcas de tiempo.

Según sus comentarios, parece quererlo como una marca de tiempo UNIX de alta precisión. Algo así como DateTime.Now.Ticksen el mundo .NET.

Puede usar la siguiente función para hacerlo:

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

¡Esa es la manera de hacerlo!
tonix

1
perrrrrrfect .. ♥.
SRB prohíbe

¿No es devolver la hora del servidor? En mi caso, veo que el tiempo almacenado en db es el tiempo de mi navegador local. Supongamos que la zona horaria de mi servidor es EST + 3 y la hora de mi navegador es GMT + 6, aunque envío un formulario desde la ubicación GMT + 6, veo que la hora almacenada es GMT + 6 milisegundos de tiempo equivalente. ¿Entonces, cuál es el problema? :(
Zenith

12

Usar microtime(true)en PHP 5, o la siguiente modificación en PHP 4:

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

Una forma portátil de escribir ese código sería:

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

salida:

2016-11-19 15:12:34.346351


1
Esto usa la misma marca de tiempo:$t = gettimeofday(); echo date('Y-m-d H:i:s.',$t['sec']) . $t['usec'];
Savvas Radevic

microsegundos deben estar rellenados con cero:$timeofday=gettimeofday(); echo sprintf("%s.%06d", date('Y-m-d H:i:s', $timeofday['sec']), $timeofday['usec']);
mabi

7

prueba esto:

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

7

Esto funciona incluso si está en 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'

Tenga en cuenta que esto no le da enteros, sino cadenas. Sin embargo, esto funciona bien en muchos casos, por ejemplo, al crear URL para solicitudes REST.


Si necesita números enteros, PHP de 64 bits es obligatorio.

Luego puede reutilizar el código anterior y enviarlo a (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

O puedes usar las buenas frases antiguas:

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

NOTA: Se requiere PHP5 para esta función debido a las mejoras con microtime () y también se requiere el módulo matemático bc (ya que estamos tratando con números grandes, puede verificar si tiene el módulo en phpinfo).

Espero que esto te ayude.


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

¿Es eso realmente como rellenar tres ceros a la derecha?
Zeeshan

De ningún modo. Convierte ambas partes en milisegundos y da la suma. Por lo tanto, es más preciso que agregar ceros.
user3767296

1
Si bien este fragmento de código puede resolver la pregunta, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no saber los motivos de su sugerencia de código. ¡Intente también no saturar su código con comentarios explicativos, esto reduce la legibilidad tanto del código como de las explicaciones!
Michał Perłakowski

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 

1
En php <7.1 los nuevos microsegundos DateTime () siempre son 0, vea php.net/manual/en/migration71.incompatible.php .
mabi

-2

Utilizar este:

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

Adiós

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.