получение формата даты mdY H: i: su из миллисекунд


117

Я пытаюсь получить отформатированную дату, включая микросекунды из миллисекунд.

Единственная проблема в том, что я получаю 000000

date("m-d-Y H:i:s.u", $milliseconds/1000);

ех. 28.07.2013 11: 26: 14.000000


6
Странно, что вопрос требует конвертировать миллисекунды , но все отвечают, как конвертировать микросекунды. Я знаю, что вы можете конвертировать между обоими, но на самом деле было бы неплохо ответить на вопрос вместо того, чтобы копировать и вставлять несвязанный код из документа PHP или где-либо еще.
Laurent

Я знаю, что это было давно, но ответ Бамосса был лучшим, что я нашел здесь
Пийин

Ответы:


123

php.net говорит:

Микросекунды (добавлено в PHP 5.2.2). Обратите внимание, что date()всегда будет генерироваться, 000000поскольку он принимает целочисленный параметр, тогда DateTime::format()как поддерживает микросекунды, если DateTimeбыл создан с помощью микросекунд.

Так что используйте просто:

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

Рекомендуется и используйте dateTime()класс из указанного:

$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"); // note at point on "u"

Примечание u- микросекунды (1 секунда = 1000000 мкс).

Другой пример с php.net :

$d2=new DateTime("2012-07-08 11:14:15.889342");

Ссылка dateTime()на php.net

Я ответил на вопрос кратко и упрощенно для автора. См. Дополнительную информацию для автора: получение формата даты mdY H: i: su из миллисекунд


4
Я обычно выбираю вторую форму, так как ее легче читать и понимать. Кроме того, DateTime гораздо более гибок и надежен, чем функции даты / времени. Примером может служить обработка микросекунд.
Герберт

3
@Geo и AlBundy, может быть, вы пробуете это на машине с php <5.2.2? PHP 5.4.39 работает отлично ...
Ричард Бернардс,

это было бы легко? date ('mdY H: i: s'). (int) microtime (истина);
Анант

@Anant, это действительно было бы довольно просто. Но ошиблись. ;) То, что вы получаете, - это просто эпоха в секундах. (К сожалению, ни с microtime(false)одним из них не работает .)
Sz.

Этот код не работает правильно на всех языках. В некоторых странах, таких как Германия, вместо «.1234» пишут «0,1234» или «0,1234», поэтому ваш код дает мне следующий результат: 2012-07-08 11:14:15.0.889342
Дэниел Маршалл,

138

Вы можете легко сделать это с помощью входного формата U.u.

$now = DateTime::createFromFormat('U.u', microtime(true));
echo $now->format("m-d-Y H:i:s.u");

Это дает следующий результат:

04-13-2015 05:56:22.082300

На странице руководства PHP для форматов даты:

  • U = секунды с эпохи Unix
  • u = микросекунды

http://php.net/manual/en/function.date.php


Спасибо giggsey за указание на ошибку в моем первоначальном ответе, добавление number_format()в строку должно исправить случай точной секунды. Жаль, что это уже не так элегантно ...

$now = DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', ''));

http://php.net/manual/en/function.number-format.php


Заметка о часовых поясах в ответ на DaVe.

Обычно createFromFormat()метод будет использовать местный часовой пояс, если он не указан.

http://php.net/manual/en/datetime.createfromformat.php

Однако описанный здесь метод инициализирует объект DateTime, с помощью microtime()которого возвращается количество секунд, прошедших с начала эпохи Unix (01 января 1970 г., 00:00:00 по Гринвичу).

http://php.net/manual/en/function.microtime.php

Это означает, что объект DateTime неявно инициализируется в формате UTC, что хорошо для внутренних задач сервера, которые просто хотят отслеживать прошедшее время.

Если вам нужно отобразить время для определенного часового пояса, вам необходимо установить его соответствующим образом. Однако это должно быть сделано как отдельный шаг после инициализации ( без использования третьего параметра createFromFormat()) по причинам, обсужденным выше.

В setTimeZone() метод можно использовать для выполнения этого требования.

http://php.net/manual/en/datetime.settimezone.php

Например:

$now = DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', ''));
echo $now->format("m-d-Y H:i:s.u") . '<br>';

$local = $now->setTimeZone(new DateTimeZone('Australia/Canberra'));
echo $local->format("m-d-Y H:i:s.u") . '<br>';

Производит следующий вывод:

10-29-2015 00:40:09.433818
10-29-2015 11:40:09.433818

Обратите внимание, что если вы хотите ввести данные в mysql, формат времени должен быть:

format("Y-m-d H:i:s.u")

19
Примечание: DateTime::createFromFormat('U.u', microtime(true));вернет false, если microtime(true)выполняется точно в секунду. Он возвращает «1438616239» вместо «1438616239.000000».
giggsey 03

1
Отличное решение, спасибо. Кажется, я теряю свое местное время, создавая $ сейчас из микровремени. Любая идея?
daVe

1
@daVe Я добавил информацию о часовых поясах, надеюсь, это то, что вам нужно.
ArchCodeMonkey

1
number_formatВсегда необходимо, даже если это не на точную секунду. В противном случае вы зависите от параметра precisionконфигурации PHP (для «отображения»), который по умолчанию недостаточно высок, начиная с PHP 7.0, что приводит к потере точности (с точностью до микросекунды).
Теох Хан Хуэй,

1
Всегда прокручивайте вниз в StackOverflow
tom10271

15

Вот более короткий подход. Вместо того, чтобы работать над созданием высокоточной числовой даты / времени, я конвертирую значение микросекунды в строку, удаляю 0и добавляю его в конец строки даты / времени. Я могу легко уменьшить количество десятичных знаков, отрегулировав параметр длины строки; здесь я использую 4для получения миллисекунд, но вы можете использовать 7для получения микросекунд.

$t = explode(" ",microtime());
echo date("m-d-y H:i:s",$t[1]).substr((string)$t[0],1,4);

Для значения microtime () 0.98236000 1407400573это возвращается 08-07-14 01:08:13.982.


9

Я использую

echo date("Y-m-d H:i:s.").gettimeofday()["usec"];

output: 2017-09-05 17:04:57.555036

6
echo date('m-d-Y H:i:s').substr(fmod(microtime(true), 1), 1);

пример вывода:

02-06-2019 16:45:03.53811192512512

Если вам необходимо ограничить количество знаков после запятой, то хорошей альтернативой будет строка ниже (кредитный балл). (В приведенном ниже коде число 6 ограничивает количество десятичных знаков до 6.)

echo date('m-d-Y H:i:').sprintf('%09.6f', date('s')+fmod(microtime(true), 1));

пример вывода:

02-11-2019 15:33:03.624493

Вы упустили точность и на несколько секунд опередили ноль. Так и должна быть правильная версия echo date('m-d-Y H:i:').sprintf('%09.6f', date('s')+fmod(microtime(true), 1));. Объяснение, почему нам нужно 09: stackoverflow.com/a/28739819/318765
mgutt

Вы снова упустили точность;)echo date('H:i:s').substr(fmod(microtime(true), 1), 1, 7);
mgutt

Но будьте осторожны, substr()не круглые. И в сочетании с round()ним бы сократить конечные нули: stackoverflow.com/questions/7493305/… Вот почему я сделал предложение sprintf().
mgutt

@mgutt Когда первая цифра не будет нулем? По сути, необходимо просто удалить ноль, который всегда присутствует при получении остатка от fmod на 1. Вопрос запрашивает микросекунды, но в виде десятичных знаков секунд. Нет причин ограничивать количество десятичных знаков. Чем больше десятичных знаков, тем лучше точность.
ghbarratt

@mgutt Я добавил вашу первую предложенную альтернативу к своему ответу, объяснив, что это был бы хороший способ ограничить количество десятичных знаков, если это необходимо
ghbarratt

3

Если вы (new Date()).toISOString()по какой-то причине хотите отформатировать дату как в JavaScript , это можно сделать в PHP следующим образом:

$now = microtime(true);
gmdate('Y-m-d\TH:i:s', $now).sprintf('.%03dZ',round(($now-floor($now))*1000));

Пример вывода:

2016-04-27T18:25:56.696Z

Просто чтобы доказать, что вычитание целого числа не снижает точность десятичной части:

>>> number_format(123.01234567890123456789,25)
=> "123.0123456789012408307826263"
>>> number_format(123.01234567890123456789-123,25)
=> "0.0123456789012408307826263"

PHP сделал вокруг знаков после запятой, но закругленные их точно так же в обоих случаях.


1
Нет. Не используйте математику для чисел с плавающей запятой, это неточно. Также не тратьте время на вызов нескольких функций. Просто используйте substr (), чтобы усечь отформатированную дату до трех десятичных знаков.
LS

@LS Усечение не округляет третий десятичный знак, что, вероятно, еще более неточно. Поплавки не ломаются, пока вы не добьетесь очень крошечной точности; 3 десятичных разряда вполне подойдут. На самом деле, я не думаю, что я вообще изменяю точность, числа с плавающей запятой становятся тем точнее, чем ближе вы приближаетесь к 0. Вычитание целого числа не должно изменять десятичные разряды AFAIK.
mpen

О чем date('Y-m-d\TH:i:s', $time / 1000) . sprintf('.%03dZ', substr($time, 10));?
F8ER,

@ F8ER Если у вас $timeуже есть миллисекунды, да, технически это сработает. Не люблю этот substrхакер, но думаю, он сработает для дат между 2001 и 2286 годами.
mpen

Да, $timeэто MS, но как насчет того 2286, почему я так считаю и как можно было бы избежать такого?
F8ER

3

Это основано на ответе ArchCodeMonkey.

Но просто упрощенно, если вам просто нужно что-то быстрое, что работает.

function DateTime_us_utc(){
    return DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', ''));
}
function DateTime_us(){
    $now = DateTime_us_utc();
    return $now->setTimeZone(new DateTimeZone(date_default_timezone_get()));
}

Так что для меня тогда

$now = DateTime_us();
$now->format("m-d-Y H:i:s.u");

3

Вот еще один метод, который я считаю немного более элегантным / простым:

echo date('Y-m-d-H:i:s.').preg_replace("/^.*\./i","", microtime(true));

2

Начиная с PHP 7.1, вы можете просто сделать это:

$date = new DateTime( "NOW" );
echo $date->format( "m-d-Y H:i:s.u" );

Он будет отображаться как:

04-11-2018 10:54:01.321688

1
// Procedural
$fineStamp = date('Y-m-d\TH:i:s') . substr(microtime(), 1, 9);
echo $fineStamp . PHP_EOL;

// Object-oriented (if you must). Still relies on $fineStamp though :-\
$d = new DateTime($fineStamp);
echo $d->format('Y-m-d\TH:i:s.u') . PHP_EOL;

0

В документации сказано следующее:

Микросекунды (добавлено в PHP 5.2.2). Обратите внимание, что date () всегда будет генерировать 000000, поскольку принимает целочисленный параметр, тогда как DateTime :: format () поддерживает микросекунды.

Т.е. вместо этого используйте DateTime.


6
Это не работает! date_format (new DateTime (), 'u') дает нули: phpfiddle.org/lite/code/ggh-mvz
Янис Элмерис

Да, согласно приведенному выше ответу (и моим испытаниям) new DateTime()также вернет 0000 для u. Но если вы предоставите ему время с точностью до микросекунд при его создании, он будет работать нормально.
scipilot

@scipilot, хорошо, как ты это делаешь?
Geo

@Geo см. Принятый ответ. new DateTime( 'Y-m-d H:i:s.'.$micro);
scipilot

0

Теперь с PHP 7.0+ вы можете делать следующее:

$dateString = substr($millseconds_go_here,0,10);
$drawDate = new \DateTime(Date('Y-m-d H:i',$dateString));
$drawDate->setTimezone(new \DateTimeZone('UTC'));

Это делает следующее по порядку:

  1. Обрезает последние 4 нуля строки, чтобы Date()можно было обрабатывать дату.
  2. Использует дату для форматирования миллисекунд в строку даты и времени, которую может понять DateTime.
  3. DateTime()может затем позволить вам изменить часовой пояс, в котором вы находитесь, но убедитесь, что date_default_timezone_set("Timezone");он установлен, прежде чем использоватьDateTime() функции и классы.
  4. Рекомендуется использовать конструктор в своих классах, чтобы убедиться, что вы DateTime()находитесь в правильном часовом поясе при использовании классов или функций.

0

если вы используете Carbon, вы можете использовать определенную спецификацию «RFC3339_EXTENDED». или настроить его.

Carbon::RFC3339_EXTENDED = 'Y-m-d\TH:i:s.vP';

0

На основе ответа @ArchCodeMonkey.

Если у вас есть, declare(strict_types=1)вы должны привести второй аргумент к строке

введите описание изображения здесь


0

Я жал несколькими способами:

1) microtime + sscanf + дата:

sscanf(microtime(), '0.%6s00 %s', $usec, $sec);
$date = date('Y-m-d H:i:s.', $sec) . $usec;

Я не уверен, почему microtime () возвращает 10 символов (0.dddddd00) для микросекундной части, но, может быть, кто-нибудь скажет мне?

$start_ts = microtime(true); for($i = 0; $i < 10000000; $i++) { sscanf(microtime(), '0.%6s00 %s', $usec, $sec); $date = date('Y-m-d H:i:s.', $sec) . $usec; } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "22372.335910797 ms" // macOS PHP 5.6.30
string(18) "16772.964000702 ms" // Linux PHP 5.4.16
string(18) "10382.229089737 ms" // Linux PHP 7.3.11 (same linux box as above)

2) DateTime :: createFromFormat + Datetime-> формат:

$now = new DateTime('NOW');
$date = $now->format('Y-m-d H:i:s.u');

не работает в PHP 5.x ...

$start_ts = microtime(true); for($i = 0; $i < 10000000; $i++) { $now = new DateTime('NOW'); $date = $now->format('Y-m-d H:i:s.u'); } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "45801.825046539 ms" // macOS PHP 5.6.30 (ms not working)
string(18) "21180.155038834 ms" // Linux PHP 5.4.16 (ms not working)
string(18) "11879.796028137 ms" // Linux PHP 7.3.11 (same linux box as above)

3) gettimeofday + date:

$time = gettimeofday();
$date = date('Y-m-d H:i:s.', $time['sec']) . $time['usec'];

-

$start_ts = microtime(true); for($i = 0; $i < 10000000; $i++) { $time = gettimeofday(); $date = date('Y-m-d H:i:s.', $time['sec']) . $time['usec']; } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "23706.788063049 ms" // macOS PHP 5.6.30
string(18) "14984.534025192 ms" // Linux PHP 5.4.16
string(18) "7799.1390228271 ms" // Linux PHP 7.3.11 (same linux box as above)

4) microtime + number_format + DateTime :: createFromFormat + DateTime-> формат:

$now = DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', ''));
$date = $now->format('Y-m-d H:i:s.u');

-

$start_ts = microtime(true); for($i = 0; $i < 10000000; $i++) { $now = DateTime::createFromFormat('U.u', number_format(microtime(true), 6, '.', '')); $date = $now->format('Y-m-d H:i:s.u'); } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "83326.496124268 ms" // macOS PHP 5.6.30
string(18) "61982.603788376 ms" // Linux PHP 5.4.16
string(16) "19107.1870327 ms" // Linux PHP 7.3.11 (same linux box as above)

5) формат microtime + sprintf + DateTime :: createFromFormat + DateTime->:

$now = DateTime::createFromFormat('U.u', sprintf('%.6f', microtime(true)));
$date = $now->format('Y-m-d H:i:s.u');

-

$start_ts = microtime(true); for($i = 0; $i < 10000000; $i++) { $now = DateTime::createFromFormat('U.u', sprintf('%.6f', microtime(true))); $date = $now->format('Y-m-d H:i:s.u'); } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "79387.331962585 ms" // macOS PHP 5.6.30
string(18) "60734.437942505 ms" // Linux PHP 5.4.16
string(18) "18594.941139221 ms" // Linux PHP 7.3.11 (same linux box as above)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.