from - strtotime formats php
PHP DateTime microsegundos siempre devuelve 0 (18)
este código siempre devuelve 0 en PHP 5.2.5 por microsegundos:
<?php
$dt = new DateTime();
echo $dt->format("Y-m-d/TH:i:s.u") . "/n";
?>
Salida:
[root@www1 ~]$ php date_test.php
2008-10-03T20:31:26.000000
[root@www1 ~]$ php date_test.php
2008-10-03T20:31:27.000000
[root@www1 ~]$ php date_test.php
2008-10-03T20:31:27.000000
[root@www1 ~]$ php date_test.php
2008-10-03T20:31:28.000000
¿Algunas ideas?
¿Qué tal esto?
$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>";
Muestra de salida
2013-07-17 08: 23: 37: 0.88862400
Algunas respuestas hacen uso de varias marcas de tiempo, lo que es conceptualmente incorrecto, y pueden ocurrir problemas de superposición: segundos de 21:15:05.999
combinados por microsegundos de 21:15:06.000
dan 21:15:05.000
.
Aparentemente, lo más simple es utilizar DateTime::createFromFormat()
con Uu
, pero como se indica en un comentario , falla si no hay microsegundos.
Entonces, sugiero este código:
function udate($format, $time = null) {
if (!$time) {
$time = microtime(true);
}
// Avoid missing dot on full seconds: (string)42 and (string)42.000000 give ''42''
$time = number_format($time, 6, ''.'', '''');
return DateTime::createFromFormat(''U.u'', $time)->format($format);
}
Bien, me gustaría aclarar esto de una vez por todas.
Una explicación de cómo mostrar la fecha y hora del formato ISO 8601 en PHP con mili segundos y micro segundos ...
mili segundos o ''ms'' tienen 4 dígitos después del punto decimal, por ejemplo, 0.1234. micro segundos o ''μs'' tienen 7 dígitos después de decimal. Explicación de fracciones / nombres de segundos here
La función de date()
de PHP date()
no se comporta del todo como se esperaba con milisegundos o microsegundos, ya que solo se exceptuará un entero, como se explica en los documentos de fecha php bajo el carácter de formato ''u''.
Basado en la idea de comentario de Lucky ( here ), pero con la sintaxis corregida de PHP y el manejo adecuado del formato de los segundos (el código de Lucky agregó un ''0'' extra incorrecto después de los segundos)
Estos también eliminan las condiciones de carrera y formatea correctamente los segundos.
Fecha de PHP con mili segundos
Equivalente de trabajo de la date(''Ymd H:i:s'').".$milliseconds";
list($sec, $usec) = explode(''.'', microtime(true));
echo date(''Y-m-d H:i:s.'', $sec) . $usec;
Salida = 2016-07-12 16:27:08.5675
Fecha de PHP con micro segundos
Equivalente de trabajo de la date(''Ymd H:i:s'').".$microseconds";
o date(''Ymd H:i:s.u'')
si la función de fecha se comportó como se esperaba con microsegundos / microtime()
/ ''u''
list($usec, $sec) = explode('' '', microtime());
echo date(''Y-m-d H:i:s'', $sec) . substr($usec, 1);
Salida = 2016-07-12 16:27:08.56752900
Cadena en un formato aceptado por strtotime () ¡Funciona!
Dentro de una aplicación que estoy escribiendo tengo la necesidad de configurar / mostrar microtime en objetos DateTime. Parece que la única forma de hacer que el objeto DateTime reconozca microsegundos es inicializándolo con la hora en formato "AAAA-MM-DD HH: MM: SS.uuuuuu". El espacio entre las partes de fecha y hora también puede ser una "T", como es habitual en el formato ISO8601.
La siguiente función devuelve un objeto DateTime inicializado en la zona horaria local (el código se puede modificar según sea necesario, por supuesto, para satisfacer las necesidades individuales):
// Return DateTime object including microtime for "now"
function dto_now()
{
list($usec, $sec) = explode('' '', microtime());
$usec = substr($usec, 2, 6);
$datetime_now = date(''Y-m-d H:i:s/.'', $sec).$usec;
return new DateTime($datetime_now, new DateTimeZone(date_default_timezone_get()));
}
Esta función se extrajo de http://us3.php.net/date
function udate($format, $utimestamp = null)
{
if (is_null($utimestamp))
$utimestamp = microtime(true);
$timestamp = floor($utimestamp);
$milliseconds = round(($utimestamp - $timestamp) * 1000000);
return date(preg_replace(''`(?<!////)u`'', $milliseconds, $format), $timestamp);
}
echo udate(''H:i:s.u''); // 19:40:56.78128
Es muy complicado implementar esta función para hacer que "tú" trabaje ...: /
Este debería ser el más flexible y preciso:
function udate($format, $timestamp=null) {
if (!isset($timestamp)) $timestamp = microtime();
// microtime(true)
if (count($t = explode(" ", $timestamp)) == 1) {
list($timestamp, $usec) = explode(".", $timestamp);
$usec = "." . $usec;
}
// microtime (much more precise)
else {
$usec = $t[0];
$timestamp = $t[1];
}
// 7 decimal places for "u" is maximum
$date = new DateTime(date(''Y-m-d H:i:s'' . substr(sprintf(''%.7f'', $usec), 1), $timestamp));
return $date->format($format);
}
echo udate("Y-m-d/TH:i:s.u") . "/n";
echo udate("Y-m-d/TH:i:s.u", microtime(true)) . "/n";
echo udate("Y-m-d/TH:i:s.u", microtime()) . "/n";
/* returns:
2015-02-14T14:10:30.472647
2015-02-14T14:10:30.472700
2015-02-14T14:10:30.472749
*/
Este método es más seguro que la respuesta aceptada:
date(''Y-m-d H:i:s.'') . str_pad(substr((float)microtime(), 2), 6, ''0'', STR_PAD_LEFT)
Salida:
2012-06-01 12:00:13.036613
Actualización: No recomendado (ver comentarios)
Esto funcionó para mí y es un simple juego de tres líneas:
function udate($format=''Y-m-d H:i:s.'', $microtime=NULL) {
if(NULL === $microtime) $microtime = microtime();
list($microseconds,$unix_time) = explode('' '', $microtime);
return date($format,$unix_time) . array_pop(explode(''.'',$microseconds));
}
Esto, de manera predeterminada (sin parámetros proporcionados) devolverá una cadena en este formato para el microsegundo actual que se llamó:
AAAA-MM-DD HH: MM: SSUUUUUUUU
Una aún más simple / más rápida (aunque con solo la mitad de precisión) sería la siguiente:
function udate($format=''Y-m-d H:i:s.'', $microtime=NULL) {
if(NULL === $microtime) $microtime = microtime(true);
list($unix_time,$microseconds) = explode(''.'', $microtime);
return date($format,$unix_time) . $microseconds;
}
Este se imprimiría en el siguiente formato:
AAAA-MM-DD HH: MM: SSUUUU
Esto parece funcionar, aunque parece ilógico que http://us.php.net/date documente el especificador de microsegundos, pero en realidad no lo admite:
function getTimestamp()
{
return date("Y-m-d/TH:i:s") . substr((string)microtime(), 1, 8);
}
La documentación de PHP dice claramente " Tenga en cuenta que date () siempre generará 000000 ya que toma un parámetro entero ... ". Si desea un reemplazo rápido para la función de date()
, use la siguiente función:
function date_with_micro($format, $timestamp = null) {
if (is_null($timestamp) || $timestamp === false) {
$timestamp = microtime(true);
}
$timestamp_int = (int) floor($timestamp);
$microseconds = (int) round(($timestamp - floor($timestamp)) * 1000000.0, 0);
$format_with_micro = str_replace("u", $microseconds, $format);
return date($format_with_micro, $timestamp_int);
}
(disponible como esencia aquí: date_with_micro.php )
Prueba esto y muestra micro segundos:
$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");
Puede especificar que su entrada contiene microsegundos al construir un objeto DateTime
, y usar microtime(true)
directamente como entrada.
Desafortunadamente, esto fallará si tocas un segundo exacto, porque no habrá .
en la salida de microtime; así que use sprintf
para forzarlo a contener un .0
en ese caso:
date_create_from_format(
''U.u'', sprintf(''%.f'', microtime(true))
)->format(''Y-m-d/TH:i:s.uO'');
O equivalente (más estilo OO)
DateTime::createFromFormat(
''U.u'', sprintf(''%.f'', microtime(true))
)->format(''Y-m-d/TH:i:s.uO'');
Sobre la base del comentario de Lucky, escribí una forma sencilla de almacenar mensajes en el servidor. En el pasado, he usado hashes e incrementos para obtener nombres de archivo únicos, pero la fecha con microsegundos funciona bien para esta aplicación.
// Create a unique message ID using the time and microseconds
list($usec, $sec) = explode(" ", microtime());
$messageID = date("Y-m-d H:i:s ", $sec) . substr($usec, 2, 8);
$fname = "./Messages/$messageID";
$fp = fopen($fname, ''w'');
Este es el nombre del archivo de salida:
2015-05-07 12:03:17 65468400
Trabajando desde el comment de Lucky y esta solicitud de función en la base de datos de errores de PHP , uso algo como esto:
class ExtendedDateTime extends DateTime {
/**
* Returns new DateTime object. Adds microtime for "now" dates
* @param string $sTime
* @param DateTimeZone $oTimeZone
*/
public function __construct($sTime = ''now'', DateTimeZone $oTimeZone = NULL) {
// check that constructor is called as current date/time
if (strtotime($sTime) == time()) {
$aMicrotime = explode('' '', microtime());
$sTime = date(''Y-m-d H:i:s.'' . $aMicrotime[0] * 1000000, $aMicrotime[1]);
}
// DateTime throws an Exception with a null TimeZone
if ($oTimeZone instanceof DateTimeZone) {
parent::__construct($sTime, $oTimeZone);
} else {
parent::__construct($sTime);
}
}
}
$oDate = new ExtendedDateTime();
echo $oDate->format(''Y-m-d G:i:s.u'');
Salida:
2010-12-01 18:12:10.146625
date (''u'') solo es compatible con PHP 5.2. ¡Tu PHP puede ser más viejo!
time: Cadena en un formato aceptado por strtotime (), por defecto es "ahora".
time: la cadena para analizar, de acuerdo con la sintaxis GNU »Date Input Formats. Antes de PHP 5.0.0, microsegundos no estaban permitidos en el tiempo, ya que PHP 5.0.0 están permitidos pero ignorados.
/DateTime::createFromFormat(''U.u'', microtime(true));
Le dará (al menos en la mayoría de los sistemas):
object(DateTime)(
''date'' => ''2015-03-09 17:27:39.456200'',
''timezone_type'' => 3,
''timezone'' => ''Australia/Darwin''
)
Pero hay una pérdida de precisión debido al redondeo de flotación de PHP. No es realmente microsegundos.
Actualizar
Este es probablemente el mejor compromiso de las opciones de createFromFormat()
y proporciona una precisión total.
/DateTime::createFromFormat(''0.u00 U'', microtime());
gettimeofday ()
Más explícito, y tal vez más robusto. Resuelve el error encontrado por Xavi.
$time = gettimeofday();
/DateTime::createFromFormat(''U.u'', sprintf(''%d.%06d'', $time[''sec''], $time[''usec'']));