PHP DateTime микросекунд всегда возвращает 0
этот код всегда возвращает 0 в PHP 5.2.5 в течение микросекунд:
<?php
$dt = new DateTime();
echo $dt->format("Y-m-dTH: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 ответов:
это, кажется, работает, хотя кажется нелогичным, что http://us.php.net/date документы спецификатор микросекунды еще не поддерживает его:
function getTimestamp() { return date("Y-m-d\TH:i:s") . substr((string)microtime(), 1, 8); }
вы можете указать, что ваш вход содержит микросекунды при построении
DateTime
объект, и использоватьmicrotime(true)
сразу как входной сигнал.к сожалению, это не удастся, если вы попали в туже секунду, потому что не будет
.
в выводе microtime; так что используйте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');
эта функция извлекается из 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" работать... :\
попробуйте это, и он показывает микро секунд:
$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");
\DateTime::createFromFormat('U.u', microtime(true));
даст вам (по крайней мере на большинстве систем):
object(DateTime)( 'date' => '2015-03-09 17:27:39.456200', 'timezone_type' => 3, 'timezone' => 'Australia/Darwin' )
но есть потеря точности из-за PHP float округления. Это не совсем микросекунды.
обновление
это, вероятно, лучший компромисс
createFromFormat()
"параметры", и обеспечивает полную точность.\DateTime::createFromFormat('0.u00 U', microtime());
gettimeofday()
более явный и, возможно, более надежный. Решает ошибку, найденную Хави.
$time = gettimeofday(); \DateTime::createFromFormat('U.u', sprintf('%d.%06d', $time['sec'], $time['usec']));
хорошо, я хотел бы прояснить это раз и навсегда.
объяснение того, как отобразить ISO 8601 формат даты и времени в PHP с Миллисекунд и микросекунд...
Миллисекунды или " МС " имеют 4 цифры после десятичной точки, например 0,1234. микросекунды или " МКС " имеют 7 цифр после запятой. Секунды фракции / имена объяснение здесь
PHP
date()
функция ведет себя не совсем так, как ожидалось с миллисекундами или микросекундами, поскольку она будет только за исключением целого числа, как описано в php date docs под символом формата '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
это сработало для меня и представляет собой простой трехслойный:
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)); }
это по умолчанию (без параметров) возвращает строку в этом формате для текущей микросекунды, которая была вызвана:
ГГГГ-ММ-ДД ЧЧ: ММ: СС.Уууууууу
еще более простой / быстрый (хотя и с половиной точности) будет выглядеть следующим образом:
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; }
этот будет распечатан в следующем формате:
ГГГГ-ММ-ДД ЧЧ: ММ: СС.Уууу
time: строка в формате, принятом strtotime (), по умолчанию "сейчас".
время: строка для разбора, в соответствии с синтаксисом форматов ввода даты GNU. До PHP 5.0.0 микросекунды не были разрешены во времени, так как PHP 5.0.0 они разрешены, но игнорируются.
работает с повезло ' s комментарий и запрос функции в базе данных ошибок 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
Как насчет этого?
$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
Это должно быть наиболее гибким и точным:
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 */
внутри приложения, которое я пишу, мне нужно установить / отобразить microtime на объектах DateTime. Кажется, единственный способ заставить объект DateTime распознавать микросекунды-это инициализировать его со временем в формате " YYYY-MM-DD HH:MM:SS.уууууу". Пространство между частями даты и времени также может быть "T", как обычно в формате ISO8601.
следующая функция возвращает объект 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())); }
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); }
(доступно как gist здесь:date_with_micro.php)
основываясь на комментарии лаки, я написал простой способ хранения сообщений на сервере. В прошлом я использовал хэши и инкременты, чтобы получить уникальные имена файлов, но дата с микро-секундами хорошо работает для этого приложения.
// 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
некоторые ответы используют несколько временных меток, что концептуально неверно, и могут возникать перекрывающиеся проблемы: секунды от
21:15:05.999
в сочетании с микросекундами от21:15:06.000
дать21:15:05.000
.по-видимому, проще всего использовать
DateTime::createFromFormat()
СU.u
, а как указано в комментарии, он терпит неудачу, если нет микросекунд.Итак, я предлагаю этот код:
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); }