PHP DateTime микросекунды всегда возвращает 0 - PullRequest
69 голосов
/ 04 октября 2008

этот код всегда возвращает 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

Есть идеи?

Ответы [ 18 ]

26 голосов
/ 04 октября 2008

Это работает, хотя кажется нелогичным, что http://us.php.net/date документирует спецификатор микросекунды, но на самом деле не поддерживает его:

function getTimestamp()
{
        return date("Y-m-d\TH:i:s") . substr((string)microtime(), 1, 8);
}
19 голосов
/ 07 июля 2011

Вы можете указать, что ваш ввод содержит микросекунды при построении объекта DateTime, и использовать microtime(true) непосредственно в качестве ввода.

К сожалению, это не удастся, если вы нажмете точную секунду, потому что не будет . в выводе microtime; поэтому используйте sprintf, чтобы заставить его содержать .0 в этом случае:

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

Или эквивалентно (больше в стиле OO)

DateTime::createFromFormat(
    'U.u', sprintf('%.f', microtime(true))
)->format('Y-m-d\TH:i:s.uO');
16 голосов
/ 04 октября 2008

Эта функция извлечена из 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" работать ...: \

14 голосов
/ 11 декабря 2010

Попробуйте, и он показывает микросекунды:

$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");
8 голосов
/ 09 марта 2015
\DateTime::createFromFormat('U.u', microtime(true));

Даст вам (по крайней мере, на большинстве систем):

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

Но из-за округления числа с плавающей запятой в PHP теряется точность. Это не совсем микросекунды.

Обновление

Это, вероятно, лучший компромисс из опций createFromFormat() и обеспечивает полную точность.

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

gettimeofday ()

Более явный и, возможно, более надежный. Решает ошибку, найденную Хави.

$time = gettimeofday(); 
\DateTime::createFromFormat('U.u', sprintf('%d.%06d', $time['sec'], $time['usec']));
5 голосов
/ 12 июля 2016

Правильно, я хотел бы прояснить это раз и навсегда.

Объяснение того, как отображать дату и время в формате ISO 8601 в PHP с милли секундами и микро секундами ...

милли секунд или «мс» имеют 4 цифры после десятичной точки, например, 0,1234. микро секунд или 'мкс' имеют 7 цифр после десятичной дроби. Фракции / имена в секундах здесь

Функция PHP date() работает не совсем так, как ожидалось, с миллисекундами или микросекундами, поскольку она будет работать только с целым числом, как описано в документах php date в формате символа 'u'.

Основано на идее комментария Лаки ( здесь ), но с исправленным синтаксисом PHP и правильной обработкой форматирования секунд (код Лаки добавил неверный дополнительный '0' после секунд)

Они также устраняют условия гонки и правильно форматируют секунды.

PHP Дата с милли секунд

Рабочий эквивалент 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

PHP Дата с микро секунд

Рабочий эквивалент date('Y-m-d H:i:s').".$microseconds"; или date('Y-m-d H:i:s.u'), если функция даты работала как ожидалось с микросекундами / microtime() / 'u'

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

Выход = 2016-07-12 16:27:08.56752900

4 голосов
/ 04 июня 2013

Это сработало для меня и представляет собой простой три строки:

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

По умолчанию (параметры не указаны) вернет строку в этом формате для текущей микросекунды, которую она назвала:

ГГГГ-ММ-ДД ЧЧ: ММ: СС.UUUUUUUU

Еще более простой / более быстрый (хотя бы с половиной точности) будет выглядеть следующим образом:

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

Этот файл будет распечатан в следующем формате:

ГГГГ-ММ-ДД ЧЧ: ММ: СС.UUUU

1 голос
/ 04 октября 2008

date_create

time: строка в формате, принятом strtotime (), по умолчанию "now".

StrToTime

time: строка для анализа в соответствии с синтаксисом GNU »Date Input Formats. До PHP 5.0.0 микросекунды не были разрешены во времени, так как PHP 5.0.0 они разрешены, но игнорируются.

1 голос
/ 14 февраля 2015

Это должно быть максимально гибко и точно:

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 голос
/ 17 июля 2013

Как насчет этого?

$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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...