obtention du format de date mdY H: i: su à partir de millisecondes

117

J'essaie d'obtenir une date formatée, y compris les microsecondes à partir de millisecondes.

Le seul problème est que je reçois toujours 000000

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

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

slik
la source
6
C'est bizarre que la question demande la conversion des millisecondes , mais tout le monde répond comment convertir les microsecondes. Je sais que vous pouvez convertir entre les deux, mais répondre à la question au lieu de copier et coller du code non lié à partir du doc ​​PHP ou ailleurs serait bien.
laurent
Je sais que cela fait un moment, mais la réponse de bamossza était la meilleure que j'ai trouvée ici
Piyin

Réponses:

122

php.net dit:

Microsecondes (ajouté dans PHP 5.2.2). Notez que date()cela générera toujours 000000car il prend un paramètre entier, alors qu'il DateTime::format()prend en charge les microsecondes s'il a DateTimeété créé avec des microsecondes.

Alors utilisez aussi simple que cela:

$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()Classe d' utilisation et recommandée de référencée:

$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 note uest en microsecondes (1 seconde = 1000000 µs).

Un autre exemple de php.net :

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

Référence de dateTime()sur php.net

J'ai répondu à une question aussi courte et simplifiée à l'auteur. Veuillez consulter pour plus d'informations à l'auteur: obtention du format de date mdY H: i: su à partir de millisecondes

Marin Sagovac
la source
4
J'opte généralement pour le deuxième formulaire car il est plus facile à lire et à comprendre. De plus, DateTime est beaucoup plus flexible et robuste que les fonctions date / heure. La gestion des microsecondes est un cas d'espèce.
Herbert
3
@Geo et AlBundy pourrait-il être que vous essayez ceci sur une machine avec php <5.2.2? PHP 5.4.39 fonctionne parfaitement bien ...
RichardBernards
ne serait-ce pas facile? date ('mdY H: i: s'). (int) microtime (vrai);
Anant
@Anant, ce serait assez facile, en effet. Mais faux. ;) Ce que vous obtenez là n'est que l'époque en secondes. (Malheureusement, cela ne fonctionnerait pas non microtime(false)plus.)
Sz.
Ce code ne fonctionne pas correctement sur tous les paramètres régionaux. Certains pays comme l'Allemagne écrivent "0,1234" ou "0,1234" au lieu de ".1234", donc votre code donne la sortie suivante pour moi: 2012-07-08 11:14:15.0.889342
Daniel Marschall
138

Vous pouvez facilement le faire avec le format d'entrée U.u.

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

Cela produit la sortie suivante:

04-13-2015 05:56:22.082300

Depuis la page de manuel PHP pour les formats de date:

  • U = Secondes depuis l'époque Unix
  • u = microsecondes

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


Merci à Giggsey d'avoir signalé une faille dans ma réponse originale, l'ajout number_format()à la ligne devrait corriger le cas de la seconde exacte. Dommage qu'il ne soit plus aussi élégant ...

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

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


Une note sur les fuseaux horaires en réponse à DaVe.

Normalement, la createFromFormat()méthode utilisera le fuseau horaire local si aucun n'est spécifié.

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

Cependant, la technique décrite ici consiste à initialiser l'objet DateTime en utilisant microtime()qui renvoie le nombre de secondes écoulées depuis l'époque Unix (01 janvier 1970 00:00:00 GMT).

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

Cela signifie que l'objet DateTime est implicitement initialisé à UTC, ce qui convient parfaitement aux tâches internes du serveur qui souhaitent simplement suivre le temps écoulé.

Si vous avez besoin d'afficher l'heure pour un fuseau horaire particulier, vous devez le régler en conséquence. Cependant, cela doit être fait comme une étape distincte après l'initialisation ( sans utiliser le troisième paramètre de createFromFormat()) pour les raisons évoquées ci-dessus.

La setTimeZone()méthode peut être utilisée pour accomplir cette exigence.

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

Par exemple:

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

Produit la sortie suivante:

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

Notez que si vous souhaitez entrer dans mysql, le format de l'heure doit être:

format("Y-m-d H:i:s.u")
ArchCodeMonkey
la source
19
Remarque: DateTime::createFromFormat('U.u', microtime(true));retournera false si microtime(true)s'exécute à la seconde exacte. Il renvoie «1438616239» au lieu de «1438616239.000000».
giggsey
1
Excellente solution, merci. Il semble que je perds mon temps local en créant $ maintenant à partir du microtime. Une idée?
daVe
1
@daVe J'ai ajouté quelques informations sur les fuseaux horaires, j'espère que c'est ce que vous recherchiez.
ArchCodeMonkey
1
Le number_formatest toujours nécessaire, même si ce n'est pas à la seconde exacte. Sinon, vous êtes à la merci de l' precisionoption de configuration PHP (pour "display"), qui n'est pas assez haute par défaut à partir de PHP 7.0 entraînant une perte de précision (pas précise jusqu'à la microseconde).
Teoh Han Hui
1
Faites toujours défiler vers le bas dans StackOverflow
tom10271
15

Voici une approche légèrement plus courte. Plutôt que de travailler pour créer une date / heure numérique de haute précision, je convertis la valeur de la microseconde en chaîne, je supprime le 0et l'ajoute à la fin de la chaîne de date / heure. Je peux facilement couper le nombre de décimales en ajustant le paramètre de longueur de chaîne; ici, j'utilise 4pour obtenir des millisecondes, mais vous pouvez utiliser 7pour obtenir des microsecondes.

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

Pour une valeur microtime () de 0.98236000 1407400573, ceci renvoie 08-07-14 01:08:13.982.

thotso
la source
9

J'utilise

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

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

exemple de sortie:

02-06-2019 16:45:03.53811192512512

Si vous avez besoin de limiter le nombre de décimales, la ligne ci-dessous (credit mgutt) serait une bonne alternative. (Avec le code ci-dessous, le 6 limite le nombre de décimales à 6.)

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

exemple de sortie:

02-11-2019 15:33:03.624493
Ghbarratt
la source
Vous avez manqué la précision et le zéro pendant quelques secondes. La version correcte devrait donc être echo date('m-d-Y H:i:').sprintf('%09.6f', date('s')+fmod(microtime(true), 1));. Explication pourquoi nous avons besoin 09: stackoverflow.com/a/28739819/318765
mgutt
Vous avez encore manqué la précision;)echo date('H:i:s').substr(fmod(microtime(true), 1), 1, 7);
mgutt
Mais attention, substr()ne ronds pas. Et en parallèle round(), couperait les zéros de fin: stackoverflow.com/questions/7493305/ ... C'est la raison pour laquelle j'ai proposé sprintf().
mgutt
@mgutt Quand le premier chiffre ne serait-il pas un zéro? Fondamentalement, il faut simplement supprimer le zéro qui est toujours présent lors de l'obtention du reste de fmod par 1. La question demande des microsecondes mais sous la forme de décimales des secondes. Il n'y a aucune raison de limiter le nombre de décimales. Plus de décimales est simplement une meilleure précision.
ghbarratt le
@mgutt J'ai ajouté votre première alternative suggérée à ma réponse, expliquant que ce serait un bon moyen de limiter le nombre de décimales si nécessaire
ghbarratt
3

Si vous souhaitez formater une date comme celle de JavaScript (new Date()).toISOString()pour une raison quelconque, voici comment vous pouvez le faire en PHP:

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

Exemple de sortie:

2016-04-27T18:25:56.696Z

Juste pour prouver que la soustraction du nombre entier ne réduit pas la précision de la partie décimale:

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

PHP a arrondi les décimales, mais il les a arrondis de la même manière dans les deux cas.

mpen
la source
1
N'utilisez pas de maths sur le nombre à virgule flottante, c'est inexact. Ne perdez pas non plus de temps à appeler plusieurs fonctions. Utilisez simplement substr () pour tronquer la date formatée à trois décimales.
LS
@LS Truncating n'arrondira pas la 3e décimale, ce qui est probablement encore plus inexact. Les flotteurs ne se décomposent que lorsque vous entrez dans de très petites précisions; 3 décimales devraient convenir. En fait, je ne pense pas que je modifie du tout la précision, les flottants deviennent plus précis à mesure que vous vous rapprochez de 0. La soustraction du nombre entier ne devrait pas modifier les décimales AFAIK.
mpen
Et quoi date('Y-m-d\TH:i:s', $time / 1000) . sprintf('.%03dZ', substr($time, 10));?
F8ER
@ F8ER Si vous êtes $timedéjà en millisecondes, oui, cela fonctionnerait techniquement. Je n'aime pas le substrhack, mais je suppose que cela fonctionnerait pour des dates entre 2001 et 2286.
mpen
Oui, $timec'est MS, mais qu'en est-il 2286, je veux dire pourquoi pensez-vous ainsi et comment serait-il possible d'échapper à un tel?
F8ER
3

Ceci est basé sur la réponse d'ArchCodeMonkey.

Mais simplement simplifié, si vous voulez juste quelque chose de rapide qui fonctionne.

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

Alors pour moi alors

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

Voici une autre méthode que je trouve légèrement plus élégante / simple:

echo date('Y-m-d-H:i:s.').preg_replace("/^.*\./i","", microtime(true));
SDpyro
la source
2

Depuis PHP 7.1, vous pouvez simplement faire ceci:

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

Il s'affichera comme:

04-11-2018 10:54:01.321688
Harveyhase68
la source
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;
Géo
la source
0

La documentation dit ce qui suit:

Microsecondes (ajouté dans PHP 5.2.2). Notez que date () générera toujours 000000 car il prend un paramètre entier, alors que DateTime :: format () prend en charge les microsecondes.

Ie, utilisez plutôt DateTime.

Havsmonstret
la source
6
Cela ne fonctionne pas! date_format (new DateTime (), 'u') donne des zéros: phpfiddle.org/lite/code/ggh-mvz
Jānis Elmeris
Oui, selon la réponse ci-dessus (et mes essais) new DateTime()renverra également 0000 pour u. Mais si vous lui fournissez un temps de précision de l'ordre de la microseconde lors de son instanciation, cela fonctionne bien.
scipilot
@scipilot ok, alors comment fais-tu ça?
Geo
@Geo voir la réponse acceptée. new DateTime( 'Y-m-d H:i:s.'.$micro);
scipilot
0

Avec PHP 7.0+ maintenant, vous pouvez faire ce qui suit:

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

Cela fait ce qui suit dans l'ordre:

  1. Coupe les 4 derniers zéros de la chaîne pour Date()pouvoir gérer la date.
  2. Utilise la date pour mettre en forme les millisecondes dans une chaîne de date et d'heure que DateTime peut comprendre.
  3. DateTime()peut alors vous permettre de modifier le fuseau horaire dans lequel vous vous trouvez, mais assurez-vous qu'il date_default_timezone_set("Timezone");est défini avant d'utiliser des DateTime()fonctions et des classes.
  4. Il est recommandé d'utiliser un constructeur dans vos classes pour vous assurer que vous DateTime()êtes dans le bon fuseau horaire lorsque des classes ou des fonctions sont utilisées.
Jamie Ross
la source
0

si vous utilisez Carbon, vous pouvez utiliser la spécification définie "RFC3339_EXTENDED". ou personnalisez-le.

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

Basé sur la réponse @ArchCodeMonkey.

Si vous avez, declare(strict_types=1)vous devez convertir le deuxième argument en chaîne

entrez la description de l'image ici

SandroMarques
la source
0

J'ai établi un banc de différentes manières:

1) microtime + sscanf + date:

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

Je ne sais pas pourquoi microtime () renvoie 10 caractères (0.dddddd00) pour la partie microsecondes mais peut-être que quelqu'un peut me le dire?

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

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

ne fonctionne pas 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-> format:

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

$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
la source