отримання формату дати 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 або деінде, було б непогано.
Лоран

Я знаю, що минув час, але відповідь Бамосса була найкращою, яку я тут знайшов
Пійін

Відповіді:


122

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 працює цілком чудово ...
RichardBernards

хіба це не буде просто? дата ('mdY H: i: s'). (int) microtime (вірно);
Анант

@Anant, все було б досить просто. Але неправильно. ;) Що ви потрапляєте туди, це лише епоха за лічені секунди. (На жаль, не працювало б ні з microtime(false)одним.)
Sz.

Цей код працює не у всіх локалях правильно. Деякі країни, такі як Німеччина, пишуть "0,1234" або "0,1234" замість ".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 GMT).

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));повернеться неправдивим, якщо microtime(true)працює точно на секунду. Він повертає "1438616239" замість "1438616239.000000".
giggsey

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

Якщо у вас є необхідність обмежити кількість десяткових знаків, то нижченаведена лінія (кредитний mgutt) буде хорошою альтернативою. (З кодом нижче, 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

Якщо ви хочете , щоб відформатувати дату , як в JavaScript (new Date()).toISOString()для якої - то причини, це те , як ви можете зробити це в 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 Truncating не окружить 3-й десятковий, що, мабуть, ще неточніше. Поплавки не руйнуються, поки ви не потрапите в дійсно крихітні точності; 3 десяткових знаки мають бути добре. Насправді, я не думаю, що я взагалі змінюю точність, поплавці стають точнішими, чим ближче до 0. Віднімання цілого числа не повинно змінювати десяткових знаків AFAIK.
mpen

Про що date('Y-m-d\TH:i:s', $time / 1000) . sprintf('.%03dZ', substr($time, 10));?
F8ER

@ F8ER Якщо ваше $timeвже в мілісекундах, так, це технічно спрацює. Не люблю substrхак, але я думаю, що це спрацює на дати між 2001 та
2286 рр.

Так, $timeце МС, але що робити 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));

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;

1

З PHP 7.1 ви можете просто зробити це:

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

Він відображатиметься як:

04-11-2018 10:54:01.321688

0

У документації зазначено наступне:

Мікросекунди (додано в PHP 5.2.2). Зауважте, що дата () завжди генерує 000000, оскільки вона приймає цілий параметр, тоді як формат DateTime :: () підтримує мікросекунди.

Тобто замість цього використовуйте DateTime.


6
Це не працює! date_format (новий DateTime (), 'u') дає нулі: phpfiddle.org/lite/code/ggh-mvz
Jānis Elmeris

Так, відповідно до відповіді вище (і мої випробування) new DateTime()також повернеться 0000 для u. Але якщо ви надаєте йому час мікросекундної точності під час миттєвого встановлення, він працює добре.
вчений пілот

@scipilot добре, так як це зробити?
Гео

@Geo дивіться прийняту відповідь. new DateTime( 'Y-m-d H:i:s.'.$micro);
вчений пілот

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 + дата:

$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.