ce code retourne toujours 0 en PHP 5.2.5 pour les microsecondes:
<?php
$dt = new DateTime();
echo $dt->format("Y-m-d\TH:i:s.u") . "\n";
?>
Production:
[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
Des idées?
Cela semble fonctionner, bien qu'il semble illogique que http://us.php.net/date documente le spécificateur de microsecondes mais ne le supporte pas vraiment:
function getTimestamp()
{
return date("Y-m-d\TH:i:s") . substr((string)microtime(), 1, 8);
}
Vous pouvez spécifier que votre entrée contient des microsecondes lors de la construction d'un objet DateTime
et utiliser microtime(true)
directement comme entrée.
Malheureusement, cela échouera si vous atteignez une seconde exacte, car il n'y aura pas de .
dans la sortie microtime; utilisez donc sprintf
pour le forcer à contenir un .0
dans ce cas:
date_create_from_format(
'U.u', sprintf('%.f', microtime(true))
)->format('Y-m-d\TH:i:s.uO');
Ou de manière équivalente (plus de style OO)
DateTime::createFromFormat(
'U.u', sprintf('%.f', microtime(true))
)->format('Y-m-d\TH:i:s.uO');
Cette fonction est tirée 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
Très compliqué, vous devez implémenter cette fonction pour que "u" fonctionne ...: \
Essayez ceci et cela montre les micro secondes:
$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");
\DateTime::createFromFormat('U.u', microtime(true));
Vous donnera (au moins sur la plupart des systèmes):
object(DateTime)(
'date' => '2015-03-09 17:27:39.456200',
'timezone_type' => 3,
'timezone' => 'Australia/Darwin'
)
Mais il y a une perte de précision à cause de PHP arrondi flottant. Ce n'est pas vraiment des microsecondes.
Mise à jour
Il s'agit probablement du meilleur compromis des options createFromFormat()
et il offre une précision totale.
\DateTime::createFromFormat('0.u00 U', microtime());
gettimeofday ()
Plus explicite et peut-être plus robuste. Résout le bug trouvé par Xavi.
$time = gettimeofday();
\DateTime::createFromFormat('U.u', sprintf('%d.%06d', $time['sec'], $time['usec']));
Bon, j'aimerais clarifier cela une fois pour toutes.
Une explication de la façon d'afficher le ISO 8601 format date et heure en PHP avec milli secondes et micro secondes ...
milli secondes ou 'ms' ont 4 chiffres après la virgule décimale par ex. 0,1234. les micro secondes ou 'µs' ont 7 chiffres après la décimale. Explication des fractions/noms en secondes ici
La fonction date()
de PHP ne se comporte pas entièrement comme prévu avec des millisecondes ou des microsecondes car elle ne fera qu'exclure un entier, comme expliqué dans les php date docs sous le caractère de format 'u'.
Basé sur l'idée de commentaire de Lucky ( ici ), mais avec la correction de la syntaxe PHP et la gestion correcte des secondes (Le code de Lucky a ajouté un "0" supplémentaire incorrect après les secondes)
Ceux-ci éliminent également les conditions de course et formate correctement les secondes.
Équivalent de travail de date('Y-m-d H:i:s').".$milliseconds";
list($sec, $usec) = explode('.', microtime(true));
echo date('Y-m-d H:i:s.', $sec) . $usec;
Sortie = 2016-07-12 16:27:08.5675
Équivalent de travail de date('Y-m-d H:i:s').".$microseconds";
ou date('Y-m-d H:i:s.u')
si la fonction date s'est comportée comme prévu avec microsecondes/microtime()
/'u'
list($usec, $sec) = explode(' ', microtime());
echo date('Y-m-d H:i:s', $sec) . substr($usec, 1);
Sortie = 2016-07-12 16:27:08.56752900
Cela a fonctionné pour moi et est un simple trois lignes:
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));
}
Par défaut (aucun paramètre fourni), cela retournera une chaîne dans ce format pour la microseconde actuelle, elle a été appelée:
AAAA-MM-JJ HH: MM: SS.UUUUUUUU
Un modèle encore plus simple/plus rapide (quoique avec seulement la moitié de la précision) serait le suivant:
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;
}
Celui-ci s'imprimerait dans le format suivant:
AAAA-MM-JJ HH: MM: SS.UUUU
Que dis-tu de ça?
$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>";
exemple de sortie
2013-07-17 08: 23: 37: 0.88862400
time: String dans un format accepté par strtotime (), par défaut "now".
time: la chaîne à analyser, selon la syntaxe GNU "Date Input Formats. Avant PHP 5.0.0, les microsecondes n'étaient pas autorisées dans le temps, depuis PHP 5.0.0 ils sont autorisés mais ignorés.
En travaillant à partir de Luckycomment et ceci demande de fonctionnalité dans la base de données PHP bug , j'utilise quelque chose comme cette:
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');
Production:
2010-12-01 18:12:10.146625
Cela devrait être le plus flexible et le plus précis:
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
*/
Certaines réponses utilisent plusieurs horodatages, ce qui est conceptuellement incorrect, et des problèmes de chevauchement peuvent survenir: des secondes de 21:15:05.999
Combinées par des microsecondes de 21:15:06.000
Donnent 21:15:05.000
.
Apparemment, le plus simple est d'utiliser DateTime::createFromFormat()
avec U.u
, Mais comme indiqué dans un commentaire , il échoue s'il n'y a pas de microsecondes.
Donc, je suggère ce code:
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);
}
Chaîne dans un format accepté par strtotime () Ça marche!
Dans une application que j'écris, j'ai besoin de définir/afficher le microtime sur les objets DateTime. Il semble que le seul moyen pour que l'objet DateTime reconnaisse les microsecondes est de l'initialiser avec l'heure au format "AAAA-MM-JJ HH: MM: SS.uuuuuu". L'espace entre les parties de date et d'heure peut également être un "T" comme c'est généralement le cas au format ISO8601.
La fonction suivante renvoie un objet DateTime initialisé dans le fuseau horaire local (le code peut bien sûr être modifié selon les besoins pour répondre aux besoins individuels):
// 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()));
}
La documentation PHP dit clairement " Notez que date () générera toujours 000000 car elle prend un paramètre entier ...". Si vous souhaitez un remplacement rapide de la fonction date()
utilisez la fonction ci-dessous:
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 sous Gist ici: date_with_micro.php )
Sur la base du commentaire de Lucky, j'ai écrit un moyen simple de stocker des messages sur le serveur. Dans le passé, j'ai utilisé des hachages et des incréments pour obtenir des noms de fichiers uniques, mais la date avec des micro-secondes fonctionne bien pour cette application.
// 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');
Voici le nom du fichier de sortie:
2015-05-07 12:03:17 65468400