it-swarm.com.de

PHP DateTime Mikrosekunden gibt immer 0 zurück

dieser Code gibt in PHP 5.2.5 für Mikrosekunden immer 0 zurück:

<?php
$dt = new DateTime();
echo $dt->format("Y-m-d\TH:i:s.u") . "\n";
?>

Ausgabe:

[[email protected] ~]$ php date_test.php
2008-10-03T20:31:26.000000
[[email protected] ~]$ php date_test.php
2008-10-03T20:31:27.000000
[[email protected] ~]$ php date_test.php
2008-10-03T20:31:27.000000
[[email protected] ~]$ php date_test.php
2008-10-03T20:31:28.000000

Irgendwelche Ideen?

70
eydelber

Dies scheint zu funktionieren, obwohl es unlogisch erscheint, dass http://us.php.net/date den Mikrosekunden-Spezifizierer dokumentiert, ihn aber nicht wirklich unterstützt:

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

Sie können angeben, dass Ihre Eingabe Mikrosekunden enthält, wenn Sie ein DateTime -Objekt erstellen, und microtime(true) direkt als Eingabe verwenden.

Leider schlägt dies fehl, wenn Sie eine Sekunde genau treffen, da die Ausgabe der Mikrotime kein . Enthält. Verwenden Sie also sprintf, um zu erzwingen, dass es in diesem Fall einen .0 enthält:

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

Oder gleichwertig (eher im OO-Stil)

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

Diese Funktion wurde von http://us3.php.net/date gezogen

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

Sehr bescheuert muss man diese Funktion implementieren, um "u" zum Laufen zu bringen ...: \

17
jmccartie

Versuchen Sie dies und es zeigt Mikrosekunden:

$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");
14
dbwebtek
\DateTime::createFromFormat('U.u', microtime(true));

Gibt Ihnen (zumindest auf den meisten Systemen):

object(DateTime)(
  'date' => '2015-03-09 17:27:39.456200',
  'timezone_type' => 3,
  'timezone' => 'Australia/Darwin'
)

Aber es gibt einen Präzisionsverlust aufgrund von PHP float rounding. Es ist nicht wirklich Mikrosekunden.

pdate

Dies ist wahrscheinlich der beste Kompromiss zwischen den createFromFormat() -Optionen und bietet volle Präzision.

\DateTime::createFromFormat('0.u00 U', microtime());

gettimeofday ()

Expliziter und vielleicht robuster. Behebt den von Xavi gefundenen Fehler.

$time = gettimeofday(); 
\DateTime::createFromFormat('U.u', sprintf('%d.%06d', $time['sec'], $time['usec']));
8
Ryan

Richtig, ich möchte das ein für alle Mal klären.

Eine Erklärung, wie das ISO 8601 Format Datum & Uhrzeit in PHP mit Milli Sekunden und Mikrosekunden ...

Millisekunden oder 'ms' haben 4 Nachkommastellen, z. 0,1234. Mikrosekunden oder 'µs' haben 7 Nachkommastellen. Sekunden Brüche/Namen Erklärung hier

Die Funktion date() von PHP verhält sich bei Millisekunden oder Mikrosekunden nicht wie erwartet, da sie nur eine Ganzzahl ausschließt, wie in php date docs unter dem Formatzeichen 'u' erläutert.

Basierend auf Luckys Kommentaridee ( hier ), aber mit korrigierter PHP Syntax und korrekter Handhabung der Sekundenformatierung (Luckys Code fügte danach eine falsche zusätzliche '0' hinzu die Sekunden)

Dadurch werden auch die Rennbedingungen beseitigt und die Sekunden korrekt formatiert.

PHP-Datum mit Millisekunden

Arbeitsäquivalent von date('Y-m-d H:i:s').".$milliseconds";

list($sec, $usec) = explode('.', microtime(true));
echo date('Y-m-d H:i:s.', $sec) . $usec;

Ausgabe = 2016-07-12 16:27:08.5675

PHP-Datum mit Mikrosekunden

Arbeitsäquivalent zu date('Y-m-d H:i:s').".$microseconds"; oder date('Y-m-d H:i:s.u'), wenn sich die Datumsfunktion wie erwartet in Mikrosekunden verhalten hat/microtime()/'u'

list($usec, $sec) = explode(' ', microtime());
echo date('Y-m-d H:i:s', $sec) . substr($usec, 1);

Ausgabe = 2016-07-12 16:27:08.56752900

5
hozza

Das hat bei mir geklappt und ist ein einfacher 3-Liner:

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

Dies gibt standardmäßig (ohne Angabe von Parametern) eine Zeichenfolge in diesem Format für die aktuelle Mikrosekunde zurück, in der sie aufgerufen wurde:

JJJJ-MM-TT HH: MM: SS.UUUUUUUU

Eine noch einfachere/schnellere (allerdings mit nur der halben Genauigkeit) wäre wie folgt:

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

Dieser würde in folgendem Format ausgedruckt:

JJJJ-MM-TT HH: MM: SS.UUUU

4
KyleFarris

Wie wäre es damit?

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

Beispielausgabe

2013-07-17 08: 23: 37: 0.88862400

1
Nadeem

date_create

time: String in einem Format, das von strtotime () akzeptiert wird, standardmäßig "now".

strtotime

time: Die zu analysierende Zeichenfolge gemäß der Syntax GNU "Date Input Formats. Vor PHP= 5.0.0 waren Mikrosekunden in der Zeit nicht zulässig. seit PHP 5.0.0 sind sie erlaubt, werden aber ignoriert.

1
scronide

Ausgehend von Lucky 's comment und diesem feature request in der PHP bug database verwende ich so etwas Dies:

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

Ausgabe:

2010-12-01 18:12:10.146625
1
enobrev

Dies sollte am flexibelsten und präzisesten sein:

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
*/
1
mgutt

Einige Antworten verwenden mehrere Zeitstempel, was konzeptionell falsch ist, und es können überlappende Probleme auftreten: Sekunden von 21:15:05.999 Kombiniert mit Mikrosekunden von 21:15:06.000 Ergeben 21:15:05.000.

Anscheinend ist es am einfachsten, DateTime::createFromFormat() mit U.u Zu verwenden, aber wie in einem Kommentar angegeben schlägt fehl, wenn keine Mikrosekunden vorliegen.

Also schlage ich diesen Code vor:

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);
}
0
Gras Double

String in einem von strtotime () akzeptierten Format Es funktioniert!

0
hosting

In einer Anwendung, die ich schreibe, muss die Mikrotime für DateTime-Objekte eingestellt/angezeigt werden. Die einzige Möglichkeit, das DateTime-Objekt zur Erkennung von Mikrosekunden zu veranlassen, besteht darin, es mit der Uhrzeit im Format "JJJJ-MM-TT HH: MM: SS.uuuuuu" zu initialisieren. Der Abstand zwischen Datum und Uhrzeit kann auch ein "T" sein, wie es im ISO8601-Format üblich ist.

Die folgende Funktion gibt ein DateTime-Objekt zurück, das für die lokale Zeitzone initialisiert wurde (der Code kann natürlich nach Bedarf geändert werden):

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

In der PHP-Dokumentation steht eindeutig " Beachten Sie, dass date () immer 000000 generiert, da es einen ganzzahligen Parameter ... verwendet". Wenn Sie einen schnellen Ersatz für die Funktion date() suchen, verwenden Sie die folgende Funktion:

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

(hier als Gist verfügbar: date_with_micro.php )

0
Manu Manjunath

Aufbauend auf Luckys Kommentar habe ich eine einfache Methode zum Speichern von Nachrichten auf dem Server geschrieben. In der Vergangenheit habe ich Hashes und Inkremente verwendet, um eindeutige Dateinamen zu erhalten, aber das Datum mit Mikrosekunden eignet sich gut für diese Anwendung.

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

Dies ist der Name der Ausgabedatei:

2015-05-07 12:03:17 65468400
0
JScarry