72 votes

PHP DateTime microseconds renvoie toujours 0

Ce code renvoie 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";
?>

Sortie :

[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 ?

0 votes

Ne date pas("A-m-d \TH :i:s.u") ont-ils moins de frais généraux ?

20 votes

Vous avez peut-être trop de chance ;)

1 votes

@Unkwntech : date() ne supporte que les entiers. Le manuel vous renvoie à date_format/DateTime::format pour l'utilisation de 'u'.

27voto

eydelber Points 441

Cela semble fonctionner, bien qu'il soit illogique que http://us.php.net/date documente le spécificateur de microseconde mais ne le supporte pas vraiment :

function getTimestamp()
{
        return date("Y-m-d\TH:i:s") . substr((string)microtime(), 1, 8);
}

17 votes

En effectuant des appels séparés, vous avez un petit risque que deux horodatages soient désordonnés : par exemple, la date de l'appel à 1:29:22.999999 et l'heure du miroir à 1:29:23.000001. Sur mon serveur, les appels consécutifs sont espacés d'environ 10 heures.

29 votes

Try : list($usec, $sec) = explode(" ", microtime()) ; return date (date("Y-m-d \TH :i:s", $sec) . $usec ;

0 votes

@eydelber : Comme la fonction PHP date() n'accepte que des timestamps entiers, le caractère de format u n'est utile que lors de l'utilisation de la fonction date_format() avec des timestamps créés par l'utilisateur avec date_create().

19voto

tr0y Points 81

Vous pouvez spécifier que votre entrée contient des microsecondes lorsque vous construisez un fichier DateTime et utiliser l'objet microtime(true) directement en entrée.

Malheureusement, cette opération échouera si vous atteignez une seconde exacte, car il n'y aura pas de . dans la sortie microtime ; il faut donc utiliser sprintf pour l'obliger à 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 proche du style OO)

DateTime::createFromFormat(
    'U.u', sprintf('%.f', microtime(true))
)->format('Y-m-d\TH:i:s.uO');

2 votes

Celle-ci échouera si microtime(true) touche une seconde entière - date_create_from_format('U.u', sprintf('%.f', microtime(true)))->format(...

0 votes

Ceci échouera également avec PHP 5.3.2 (Ubuntu 10.04) qui renvoie False lorsque 'U.u' est utilisé comme format dans cette fonction (bug).

0 votes

Malheureusement, cette solution nécessite PHP 5.3+.

17voto

jmccartie Points 1864

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

C'est très bizarre de devoir implémenter cette fonction pour que le "u" fonctionne... :\N

1 votes

Bonjour, qu'en est-il de (string)microtime(), 1, 8 ?

0 votes

+1 pour l'utilisation d'un lookbehind négatif afin de ne pas remplacer \u .

0 votes

H2ooooooo, ce n'est pas la bonne solution de toute façon, il ne supporte pas les antislashs échappés, c'est à dire " \\u "

15voto

dbwebtek Points 89

Essayez ceci et vous obtiendrez des microsecondes :

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

0 votes

Assez élégante, c'est la solution que je préfère. J'ai fait quelques tests et je n'ai trouvé aucun problème avec cette implémentation.

0 votes

Super, vous avez quelque chose d'aussi élégant à convertir en microtemps ?

0 votes

Comme vous concaténerez de toute façon les microsecondes dans une chaîne formatée, vous n'avez pas besoin de l'option DateTime objet : date('Y-m-d H:i:s.'.$micro,$t) est déjà la chaîne souhaitée (ou de manière équivalente date('Y-m-d H:i:s.',$t).$micro )

4voto

KyleFarris Points 7727

Cela a fonctionné pour moi et il s'agit d'une simple ligne de trois :

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 n'est fourni), cette fonction renvoie une chaîne de caractères dans ce format pour la microseconde à laquelle elle a été appelée :

AAAA-MM-JJ HH:MM:SS.UUUUUUUU

Une solution encore plus simple et plus rapide (bien qu'avec une précision réduite de moitié) serait la suivante :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X