pobieranie formatu daty mdY H: i: su z milisekund

117

Próbuję uzyskać sformatowaną datę, w tym mikrosekundy z milisekund.

Jedynym problemem jest to, że ciągle otrzymuję 000000

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

dawny. 07-28-2013 11:26: 14.000000

slik
źródło
6
To dziwne, że pytanie dotyczy konwersji milisekund , ale wszyscy odpowiadają, jak konwertować mikrosekundy. Wiem, że możesz konwertować między nimi, ale w rzeczywistości odpowiadanie na pytanie zamiast kopiowania i wklejania niepowiązanego kodu z dokumentu PHP lub gdzie indziej byłoby miłe.
laurent
Wiem, że minęło trochę czasu, ale odpowiedź Bamosszy była najlepsza, jaką tu znalazłem
Piyin

Odpowiedzi:

122

php.net mówi:

Mikrosekundy (dodane w PHP 5.2.2). Zauważ, że date()zawsze generuje, 000000ponieważ przyjmuje parametr całkowity, podczas DateTime::format()gdy obsługuje mikrosekundy, jeśli DateTimezostał utworzony z mikrosekundami.

Więc użyj tak prostego:

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

Zalecana i używana dateTime()klasa z przywołanych:

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

Uwaga uto mikrosekundy (1 sekunda = 1000000 µs).

Inny przykład z php.net :

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

Odniesienie do dateTime()na php.net

Odpowiedziałem na pytanie jako krótkie i uproszczone do autora. Więcej informacji dla autora: pobieranie formatu daty mdY H: i: su z milisekund

Marin Sagovac
źródło
4
Generalnie wybieram drugi formularz, ponieważ jest łatwiejszy do odczytania i zrozumienia. Ponadto DateTime jest znacznie bardziej elastyczny i niezawodny niż funkcje daty / czasu. Obsługa mikrosekund jest istotna.
Herbert
3
@Geo i AlBundy czy to możliwe, że próbujesz tego na komputerze z php <5.2.2? PHP 5.4.39 działa doskonale ...
RichardBernards
czy to nie byłoby łatwe? data („mdY H: i: s”). (int) microtime (true);
Anant
@Anant, byłoby to naprawdę łatwe. Ale źle. ;) To, co tam dostajesz, to tylko epoka w kilka sekund. (Z microtime(false)żadnym niestety nie zadziała .)
Sz.
Ten kod nie działa poprawnie we wszystkich lokalizacjach. Niektóre kraje, takie jak Niemcy, piszą „0,1234” lub „0,1234” zamiast „.1234”, dlatego Twój kod daje mi następujący wynik: 2012-07-08 11:14:15.0.889342
Daniel Marschall
138

Możesz to łatwo zrobić za pomocą formatu wejściowego U.u.

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

Daje to następujący wynik:

04-13-2015 05:56:22.082300

Ze strony podręcznika PHP dla formatów dat:

  • U = sekundy od epoki Uniksa
  • u = mikrosekundy

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


Podziękowania dla Giggsey za wskazanie błędu w mojej pierwotnej odpowiedzi, dodanie number_format()do wiersza powinno naprawić wielkość dokładnej sekundy. Szkoda, że ​​nie jest już tak elegancki ...

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

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


Uwaga dotycząca stref czasowych w odpowiedzi na DaVe.

Zwykle createFromFormat() metoda będzie używać lokalnej strefy czasowej, jeśli nie zostanie ona określona.

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

Jednak technika opisana tutaj polega na inicjalizacji obiektu DateTime za pomocą, microtime()który zwraca liczbę sekund, które upłynęły od epoki uniksowej (1 stycznia 1970 00:00:00 GMT).

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

Oznacza to, że obiekt DateTime jest niejawnie inicjowany do czasu UTC, co jest wystarczające w przypadku wewnętrznych zadań serwera, które chcą tylko śledzić upływający czas.

Jeśli chcesz wyświetlić czas dla określonej strefy czasowej, musisz go odpowiednio ustawić. Należy to jednak zrobić jako osobny krok po inicjalizacji ( nie używając trzeciego parametru z createFromFormat()) z powodów omówionych powyżej.

Plik setTimeZone()Sposób może być stosowany do realizacji tego wymagania.

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

Jako przykład:

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

Daje następujący wynik:

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

Pamiętaj, że jeśli chcesz wprowadzić dane do mysql, format czasu musi być następujący:

format("Y-m-d H:i:s.u")
ArchCodeMonkey
źródło
19
Uwaga: DateTime::createFromFormat('U.u', microtime(true));zwróci wartość false, jeśli zostanie microtime(true)uruchomiona dokładnie w sekundzie. Zwraca „1438616239” zamiast „1438616239.000000”.
giggsey
1
Świetne rozwiązanie, dziękuję. Wygląda na to, że tracę czas lokalny, tworząc teraz $ z mikroczasu. Dowolny pomysł?
daVe
1
@daVe Dodałem trochę informacji o strefach czasowych, mam nadzieję, że o to Ci chodziło.
ArchCodeMonkey
1
Plik number_format to zawsze konieczne, nawet jeśli nie jest to dokładna sekunda. W przeciwnym razie jesteś zdany na łaskę precisionopcji konfiguracyjnej PHP (dla "wyświetlania"), która domyślnie nie jest wystarczająco wysoka od PHP 7.0, powodując utratę precyzji (niedokładność do mikrosekundy).
Teoh Han Hui
1
Zawsze przewijaj w dół w StackOverflow
tom10271
15

Oto nieco krótsze podejście. Zamiast pracować nad utworzeniem liczbowej daty / godziny o wysokiej precyzji, konwertuję wartość mikrosekund na ciąg, usuwam znak 0i dodaję go na końcu ciągu daty / godziny. Mogę łatwo skrócić liczbę miejsc po przecinku, dostosowując parametr długości łańcucha; tutaj używam 4do uzyskania milisekund, ale możesz użyć 7do uzyskania mikrosekund.

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

W przypadku wartości microtime () 0.98236000 1407400573zwraca 08-07-14 01:08:13.982.

thotso
źródło
9

Używam

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

output: 2017-09-05 17:04:57.555036
bamossza
źródło
6
echo date('m-d-Y H:i:s').substr(fmod(microtime(true), 1), 1);

przykładowe dane wyjściowe:

02-06-2019 16:45:03.53811192512512

Jeśli chcesz ograniczyć liczbę miejsc po przecinku, poniższa linia (kredyt mgutt) byłaby dobrą alternatywą. (W poniższym kodzie 6 ogranicza liczbę miejsc dziesiętnych do 6).

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

przykładowe dane wyjściowe:

02-11-2019 15:33:03.624493
ghbarratt
źródło
Przegapiłeś precyzję i wiodące zero przez kilka sekund. Więc powinna być poprawna wersja echo date('m-d-Y H:i:').sprintf('%09.6f', date('s')+fmod(microtime(true), 1));. Wyjaśnienie, dlaczego potrzebujemy 09: stackoverflow.com/a/28739819/318765
mgutt
Znowu przegapiłeś precyzję;)echo date('H:i:s').substr(fmod(microtime(true), 1), 1, 7);
mgutt
Ale uwaga, substr()nie zaokrągla się. I w połączeniu z round()tym wyciąłby końcowe zera: stackoverflow.com/questions/7493305/… To jest powód, dla którego się zaproponowałem sprintf().
mgutt
@mgutt Kiedy pierwsza cyfra nie byłaby zerem? Zasadniczo potrzebne jest po prostu usunięcie zera, które jest zawsze obecne podczas pobierania reszty z fmod przez 1. Pytanie dotyczy mikrosekund, ale w postaci miejsc dziesiętnych sekund. Nie ma powodu, aby ograniczać liczbę miejsc po przecinku. Więcej miejsc po przecinku to po prostu lepsza precyzja.
ghbarratt
@mgutt Dodałem twoją pierwszą sugerowaną alternatywę do mojej odpowiedzi, wyjaśniając, że w razie potrzeby byłby to dobry sposób na ograniczenie liczby miejsc dziesiętnych
ghbarratt,
3

Jeśli (new Date()).toISOString()z jakiegoś powodu chcesz sformatować datę taką jak JavaScript , możesz to zrobić w PHP:

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

Przykładowe dane wyjściowe:

2016-04-27T18:25:56.696Z

Aby udowodnić, że odjęcie liczby całkowitej nie zmniejsza dokładności części dziesiętnej:

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

PHP zrobił wokół miejsc po przecinku, ale zaokrąglona do nich w ten sam sposób w obu przypadkach.

mpen
źródło
1
Nie. Nie używaj matematyki na liczbie zmiennoprzecinkowej, jest niedokładna. Nie trać też czasu na wywoływanie kilku funkcji. Po prostu użyj funkcji substr (), aby skrócić sformatowaną datę do trzech miejsc po przecinku.
LS
@LS Obcinanie nie zaokrągli trzeciego miejsca po przecinku, co jest prawdopodobnie jeszcze bardziej niedokładne. Pływaki nie psują się, dopóki nie osiągniesz naprawdę małych precyzji; 3 miejsca po przecinku powinny wystarczyć. Właściwie nie sądzę, żebym w ogóle zmienił precyzję, liczby zmiennoprzecinkowe stają się dokładniejsze, im bliżej się do 0. Odejmowanie liczby całkowitej nie powinno zmieniać miejsc dziesiętnych AFAIK.
otwarte
O co chodzi date('Y-m-d\TH:i:s', $time / 1000) . sprintf('.%03dZ', substr($time, 10));?
F8ER
@ F8ER Jeśli twój $timejest już w milisekundach, tak, to technicznie zadziała. Nie podoba mi się substrhack, ale myślę, że zadziała w przypadku dat między 2001 a 2286.
mpen
Tak, to $timejest stwardnienie rozsiane, ale o co chodzi 2286, mam na myśli, dlaczego tak myślisz i jak można by uciec od takiego?
F8ER
3

Jest to oparte na odpowiedzi z ArchCodeMonkey.

Ale po prostu uproszczone, jeśli potrzebujesz czegoś szybkiego, co działa.

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

Więc dla mnie

$now = DateTime_us();
$now->format("m-d-Y H:i:s.u");
John Kearney
źródło
3

Oto inna metoda, którą uważam za nieco bardziej elegancką / prostą:

echo date('Y-m-d-H:i:s.').preg_replace("/^.*\./i","", microtime(true));
SDpyro
źródło
2

Od PHP 7.1 możesz po prostu zrobić to:

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

Wyświetli się jako:

04-11-2018 10:54:01.321688
Harveyhase68
źródło
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;
Geo
źródło
0

Dokumentacja mówi, co następuje:

Mikrosekundy (dodane w PHP 5.2.2). Zauważ, że date () zawsze generuje 000000, ponieważ przyjmuje parametr będący liczbą całkowitą, podczas gdy DateTime :: format () obsługuje mikrosekundy.

Oznacza to, że zamiast tego użyj DateTime.

Havsmonstret
źródło
6
To nie działa! date_format (new DateTime (), 'u') daje zera: phpfiddle.org/lite/code/ggh-mvz
Jānis Elmeris
Tak, jak na powyższą odpowiedź (i moje próby) new DateTime()również zwróci 0000 dla u. Ale jeśli podasz mu czas z dokładnością do mikrosekund podczas tworzenia jego wystąpienia, wszystko działa poprawnie.
scipilot
@scipilot ok, więc jak to robisz?
Geo
@Geo zobacz zaakceptowaną odpowiedź. new DateTime( 'Y-m-d H:i:s.'.$micro);
scipilot
0

Dzięki PHP 7.0+ możesz teraz wykonać następujące czynności:

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

Wykonuje to w kolejności:

  1. Odcina ostatnie 4 zera z ciągu, aby Date()móc obsłużyć datę.
  2. Używa daty do sformatowania milisekund w ciągu daty i godziny, który DateTime może zrozumieć.
  3. DateTime()możesz wtedy zezwolić na zmianę strefy czasowej, w której się znajdujesz, ale upewnij się, że date_default_timezone_set("Timezone");została ustawiona przed użyciemDateTime() funkcji i klas.
  4. Dobrą praktyką jest używanie konstruktora w swoich klasach, aby upewnić się, że znajdujesz się we właściwej strefie czasowej, gdy DateTime()używane są klasy lub funkcje.
Jamie Ross
źródło
0

jeśli używasz Carbon, możesz użyć zdefiniowanej specyfikacji „RFC3339_EXTENDED”. lub dostosuj go.

Carbon::RFC3339_EXTENDED = 'Y-m-d\TH:i:s.vP';
Aiden Moon
źródło
0

Na podstawie odpowiedzi @ArchCodeMonkey.

Jeśli tak declare(strict_types=1), musisz rzucić drugi argument na łańcuch

wprowadź opis obrazu tutaj

SandroMarques
źródło
0

Wyciągałem kilka różnych sposobów:

1) microtime + sscanf + date:

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

Nie jestem pewien, dlaczego microtime () zwraca 10 znaków (0.dddddd00) dla części mikrosekundowej, ale może ktoś może mi powiedzieć?

$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-> format:

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

nie działa w 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-> format:

$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-> format:

$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)
Fravadona
źródło