Intereting Posts
php с использованием специальных символов Получите JSON из общедоступного Календаря Google регулярное выражение для соответствия доменному имени Извлечение данных из двоичных файлов с помощью php php mail и yahoo.com не vibing Php конвертировать ipv6 в число Как мы можем отправлять сообщения GCM в большом количестве 1000 в базу данных, скажем, из 10 000 зарегистрированных пользователей? AJAX & PHP: параметры GET, вызывающие ошибку ключа Flikr api PHP: call_user_func_array: передать по ссылке PHP Dynamic Include Help на Index.php? Как создать форму PHP, которая подчиняется себе? Сайт PHP / mysql с использованием utf8mb4 не будет корректно извлекать emojis из базы данных, несмотря на то, что utf8mb4 указывается везде, что я могу найти, чтобы его поместить Проблема с PHP-сессиями в WordPress с постоянными значениями по умолчанию Как определить кнопку Нажмите в расширенной строке аккордеона с несколькими ярлыками Doctrine 2 delete с построителем запросов

PHP DateTime микросекунды всегда возвращает 0

этот код всегда возвращает 0 в PHP 5.2.5 для микросекунд:

<?php $dt = new DateTime(); echo $dt->format("Ymd\TH:i:su") . "\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 

Есть идеи?

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

 function getTimestamp() { return date("Ymd\TH:i:s") . substr((string)microtime(), 1, 8); } 

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

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

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

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

 DateTime::createFromFormat( 'U.u', sprintf('%.f', microtime(true)) )->format('Ymd\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('Ymd H:i:s.'.$micro,$t) ); print $d->format("Ymd H:i:su"); 
 \DateTime::createFromFormat('U.u', microtime(true)); 

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

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

Обновить

Это решит проблему точности поплавка, ценой некоторого уродства.

 \DateTime::createFromFormat("Uu", implode(".", array_slice(gettimeofday(), 0, 2))); 

ПРЕДУПРЕЖДЕНИЕ. У этого есть ошибка, см. Комментарий ниже, когда микросекунды ниже 100000. Это означает, что 1/10-е раз эта ошибка возникает.

Обновите исправление ошибки

Сделай это:

 $now = gettimeofday(); $seconds = $now[ 'sec' ]; $microseconds = $now[ 'usec' ]; $microsecondsAsString = str_pad( ( string )$microseconds, 6, '0', STR_PAD_LEFT ); $nowAsObject = \DateTime::createFromFormat( "Uu", implode( ".", [ $seconds, $microsecondsAsString ] ) ); 

Например, это:

 <?php for( $i = 0; $i < 10; $i++ ) { $now = gettimeofday(); $seconds = $now[ 'sec' ]; $microseconds = $now[ 'usec' ]; $microsecondsAsString = str_pad( ( string )$microseconds, 6, '0', STR_PAD_LEFT ); $nowAsObject = \DateTime::createFromFormat( "Uu", implode( ".", [ $seconds, $microsecondsAsString ] ) ); echo( $nowAsObject->format( 'Ymd\TH:i:su\Z' ) . PHP_EOL ); usleep( 50000 ); } 

дал это в моей оболочке:

 2017-07-02T09:01:09.841187Z 2017-07-02T09:01:09.897125Z 2017-07-02T09:01:09.948107Z 2017-07-02T09:01:09.998798Z 2017-07-02T09:01:10.049680Z 2017-07-02T09:01:10.100515Z 2017-07-02T09:01:10.151455Z 2017-07-02T09:01:10.203247Z 2017-07-02T09:01:10.254330Z 2017-07-02T09:01:10.306189Z 

В частности, элемент 2017-07-02T09:01:10.049680Z ошибся со старым методом (было бы 10.4 вместо 10.04 ).

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

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

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

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

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

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

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

Рабочий эквивалент date('Ymd H:i:s').".$milliseconds";

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

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

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

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

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

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

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

 function udate($format='Ymd 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)); } 

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

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

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

 function udate($format='Ymd H:i:s.', $microtime=NULL) { if(NULL === $microtime) $microtime = microtime(true); list($unix_time,$microseconds) = explode('.', $microtime); return date($format,$unix_time) . $microseconds; } 

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

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

date_create

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

StrToTime

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

Работая с комментария 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('Ymd 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('Ymd G:i:s.u'); 

Вывод:

 2010-12-01 18:12:10.146625 

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

 $micro_date = microtime(); $date_array = explode(" ",$micro_date); $date = date("Ymd 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('Ymd H:i:s' . substr(sprintf('%.7f', $usec), 1), $timestamp)); return $date->format($format); } echo udate("Ymd\TH:i:su") . "\n"; echo udate("Ymd\TH:i:su", microtime(true)) . "\n"; echo udate("Ymd\TH:i:su", microtime()) . "\n"; /* returns: 2015-02-14T14:10:30.472647 2015-02-14T14:10:30.472700 2015-02-14T14:10:30.472749 */ 

Строка в формате, принятом strtotime () Это работает!

Внутри приложения, которое я пишу, мне нужно установить / отобразить microtime на объектах DateTime. Кажется, единственный способ получить объект DateTime для распознавания микросекунд – инициализировать его со временем в формате «ГГГГ-ММ-ДД ЧЧ: ММ: SS.uuuuuu». Пространство между датой и временем может также быть «Т», как обычно в формате 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('Ymd 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); } 

(доступно здесь: date_with_micro.php )

Основываясь на комментарии Lucky, я написал простой способ хранения сообщений на сервере. Раньше я использовал хеши и приращения для получения уникальных имен файлов, но дата с микросекундами хорошо работает для этого приложения.

 // Create a unique message ID using the time and microseconds list($usec, $sec) = explode(" ", microtime()); $messageID = date("Ymd 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() с Uu , но, как указано в комментарии , он терпит неудачу, если нет микросекунд.

Итак, я предлагаю этот код:

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

Этот метод безопаснее, чем принятый ответ:

 date('Ymd H:i:s.') . str_pad(substr((float)microtime(), 2), 6, '0', STR_PAD_LEFT) 

Вывод:

 2012-06-01 12:00:13.036613 

Обновление: не рекомендуется (см. Комментарии)

date ('u') поддерживается только с PHP 5.2. Ваш PHP может быть старше!