web-dev-qa-db-ja.com

PHP DateTimeマイクロ秒は常に0を返します

このコードは、常にPHP 5.2.5マイクロ秒の場合:

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

出力:

[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

何か案は?

70
eydelber

http://us.php.net/date はマイクロ秒指定子を文書化しているが、実際にはそれをサポートしていないというのは非論理的なようですが、これは機能しているようです:

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

DateTimeオブジェクトを作成するときに入力にマイクロ秒が含まれることを指定し、microtime(true)を入力として直接使用できます。

残念なことに、マイクロタイム出力に.がないため、正確な秒をヒットするとこれは失敗します。その場合、sprintfを使用して、その場合に.0を強制的に含めるようにします。

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

または同等(より多くのオブジェクト指向スタイル)

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

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

「u」を機能させるには、この関数を実装する必要があります...:\

17
jmccartie

これを試してみると、マイクロ秒が表示されます:

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

(少なくともほとんどのシステムで)以下を提供します:

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

しかし、PHP float rounding。これは本当にマイクロ秒ではありません。

更新

これはおそらくcreateFromFormat()オプションの最良の妥協案であり、完全な精度を提供します。

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

gettimeofday()

より明示的で、おそらくより堅牢です。 Xaviで見つかったバグを解決します。

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

そうです、私はこれをきっぱりと整理したいと思います。

ISO 8601 format date&time in PHP withmilliを表示する方法の説明)秒とmicro秒...

ミリ秒または「ms」には小数点以下4桁があります。 0.1234。 microsecondsまたは「µs」は、小数点以下7桁です。秒の分数/名前の説明 ここ

PHPのdate()関数は、フォーマット文字 'u'の下の php date docs で説明されているように、整数のみを除いて、ミリ秒またはマイクロ秒では完全に期待どおりに動作しません。

Luckyのコメントのアイデア( here )に基づきますが、修正されたPHP構文と秒のフォーマットを適切に処理します(Luckyのコードは間違った余分な '秒の後の0 ')

また、これらは競合状態を排除し、秒を正しくフォーマットします。

millisecondsを含むPHP Date

date('Y-m-d H:i:s').".$milliseconds";と同等の作業

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

出力= _2016-07-12 16:27:08.5675_

microsecondsを含むPHP Date

日付関数がマイクロ秒/ date('Y-m-d H:i:s').".$microseconds";/'u'で期待どおりに動作した場合、date('Y-m-d H:i:s.u')またはmicrotime()と同等の動作

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

出力= _2016-07-12 16:27:08.56752900_

5
hozza

これは私のために働いており、シンプルな3つのライナーです:

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

これは、デフォルトでは(パラメータが提供されない)、呼び出された現在のマイクロ秒に対してこの形式の文字列を返します。

YYYY-MM-DD HH:MM:SS.UUUUUUUUU

さらに単純/高速なもの(ただし、精度は半分しかありません)は次のようになります。

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

これは、次の形式で印刷されます。

YYYY-MM-DD HH:MM:SS.UUUU

4
KyleFarris

これはどう?

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

サンプル出力

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

1
Nadeem

date_create

time:strtotime()で受け入れられる形式の文字列。デフォルトは「now」です。

strtotime

time:GNU"Date Input Formats構文に従って解析する文字列。BeforePHP 5.0.0、時間内ではマイクロ秒は許可されていなかったため、 PHP 5.0.0は許可されますが、無視されます。

1
scronide

Luckyコメント とこれから PHPバグデータベース の機能リクエスト)この:

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

出力:

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

これは最も柔軟で正確でなければなりません:

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

Strtotime()で受け入れられる形式の文字列

0
hosting

私が書いているアプリケーションの内部では、DateTimeオブジェクトにマイクロタイムを設定/表示する必要があります。 DateTimeオブジェクトにマイクロ秒を認識させる唯一の方法は、「YYYY-MM-DD HH:MM:SS.uuuuuu」の形式の時刻で初期化することです。日付と時刻の部分の間のスペースは、ISO8601形式で通常のように「T」にすることもできます。

次の関数は、ローカルタイムゾーンに初期化されたDateTimeオブジェクトを返します(もちろん、個々のニーズに合わせて、必要に応じてコードを変更できます)。

// 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

PHPドキュメントでは、「date()は整数パラメーターを受け取るため、常に000000を生成することに注意してください...date()関数の迅速な置換が必要な場合は、以下の関数を使用します。

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

(ここで要点として利用可能: date_with_micro.php

0
Manu Manjunath

Luckyのコメントを基に、サーバーにメッセージを保存する簡単な方法を書きました。以前は、ハッシュと増分を使用して一意のファイル名を取得していましたが、このアプリケーションではマイクロ秒の日付が適切に機能します。

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

これは出力ファイルの名前です:

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