Jak uzyskać bieżący czas w PHP w milisekundach?


Odpowiedzi:


506

Krótka odpowiedź brzmi:

$milliseconds = round(microtime(true) * 1000);

26
@FredrikWendt, myślę, że się mylisz time(). microtime(true)z drugiej strony zwraca bieżący czas w sekundach od epoki Uniksa z dokładnością do najbliższej mikrosekundy (patrz odnośnik do PHP). W rzeczywistości bardzo łatwo jest przetestować, jeśli uruchomisz powyższy kod w pętli i wyświetlisz milisekundy.
laurent,

6
Absolutnie tak! :-)
Fredrik Wendt,

9
Podoba mi się krótka odpowiedź.
Erick Robertson

9
Czy nie powinno to być microtime(true) / 1000(podział zamiast mulitplication)?
Jordan Lev

18
@JordanLev, powinno być mnożenie, ponieważ microtime (true) zwraca uniksowy znacznik czasu w sekundach jako liczbę zmiennoprzecinkową.
laurent

88

Zastosowanie microtime. Ta funkcja zwraca ciąg oddzielony spacją. Pierwsza część to ułamkowa część sekund, druga część to część integralna. Przekaż, trueaby uzyskać jako liczbę:

var_dump(microtime());       // string(21) "0.89115400 1283846202"
var_dump(microtime(true));   // float(1283846202.89)

Jeśli używasz, uważaj na utratę precyzji microtime(true).

Istnieje również, gettimeofdayże zwraca część mikrosekund jako liczbę całkowitą.

var_dump(gettimeofday());
/*
array(4) {
  ["sec"]=>
  int(1283846202)
  ["usec"]=>
  int(891199)
  ["minuteswest"]=>
  int(-60)
  ["dsttime"]=>
  int(1)
}
*/

Mówiąc ogólnie, microtime()jest równy 1000*time(), prawda?
COMer

Rozumiem, mogą wystąpić błędy, ale błąd powinien być mniejszy niż 1000, prawda?
COMer

@COMer: O jakim wariancie mówisz?
kennytm

microtime(true)oraz1000*time()
COMer

@COMer: 1000*time()nie da milisekund. microtime(true)zwraca a, floatktóry ma 14 cyfr precyzji. Część sekund zajęła już 10, więc pozostały 4 cyfry na część mikrosekund. To powinno wystarczyć, ponieważ milisekundy wymagają tylko 3 dodatkowych cyfr.
kennytm

46

Krótka odpowiedź:

Tylko platformy 64-bitowe!

function milliseconds() {
    $mt = explode(' ', microtime());
    return ((int)$mt[1]) * 1000 + ((int)round($mt[0] * 1000));
}

[ Jeśli używasz 64-bitowego PHP, to stała PHP_INT_SIZEjest równa8 ]


Długa odpowiedź:

Jeśli chcesz najpierw uzyskać równoważną funkcję time()w milisekundach, musisz wziąć pod uwagę, że ponieważ time()zwraca liczbę sekund, które upłynęły od „czasu epoki” (01/01/1970), liczba milisekund od „czasu epoki” jest dużą liczbą i nie pasuje do 32-bitowej liczby całkowitej.

Rozmiar liczby całkowitej w PHP może wynosić 32 lub 64 bity w zależności od platformy.

Od http://php.net/manual/en/language.types.integer.php

Rozmiar liczby całkowitej jest zależny od platformy, chociaż maksymalna wartość około dwóch miliardów to zwykle wartość (to 32 bitów ze znakiem). Platformy 64-bitowe zwykle mają maksymalną wartość około 9E18, z wyjątkiem systemu Windows, który zawsze jest 32-bitowy. PHP nie obsługuje liczb całkowitych bez znaku. Rozmiar całkowity można określić za pomocą stałej PHP_INT_SIZE, a maksymalną wartość za pomocą stałej PHP_INT_MAX od PHP 4.4.0 i PHP 5.0.5.

Jeśli masz 64-bitowe liczby całkowite, możesz użyć następującej funkcji:

function milliseconds() {
    $mt = explode(' ', microtime());
    return ((int)$mt[1]) * 1000 + ((int)round($mt[0] * 1000));
}

microtime() zwraca liczbę sekund od „czasu epoki” z dokładnością do mikrosekund z dwiema liczbami oddzielonymi spacją, na przykład ...

0.90441300 1409263371

Druga liczba to sekundy (liczba całkowita), a pierwsza to część dziesiętna.

Powyższa funkcja milliseconds()przyjmuje część całkowitą pomnożoną przez1000

1409263371000

następnie dodaje część dziesiętną pomnożoną przez 1000i zaokrągloną do 0 miejsc po przecinku

1409263371904

Pamiętaj, że zarówno $mt[1]i wynik roundsą rzutowane na int. Jest to konieczne, ponieważ są one floats, a operacja na nich bez rzutowania spowoduje, że funkcja zwróci a float.

Wreszcie funkcja ta jest nieco bardziej precyzyjna niż

round(microtime(true)*1000);

że przy stosunku 1:10 (w przybliżeniu) zwraca 1 milisekundę więcej niż prawidłowy wynik. Wynika to z ograniczonej precyzji typu float ( microtime(true)zwraca float). W każdym razie, jeśli nadal wolisz krótszy round(microtime(true)*1000);, sugeruję rzutowanie intna wynik.


Nawet jeśli wykracza to poza zakres pytania, warto wspomnieć, że jeśli twoja platforma obsługuje liczby całkowite 64-bitowe, możesz również uzyskać bieżący czas w mikrosekundach bez powodowania przepełnienia.

Jeśli fakt 2^63 - 1(największa liczba całkowita ze znakiem) podzielony przez 10^6 * 3600 * 24 * 365(około mikrosekund w ciągu jednego roku) daje 292471.

To ta sama wartość, którą otrzymujesz

echo (int)( PHP_INT_MAX / ( 1000000 * 3600 * 24 * 365 ) );

Innymi słowy, 64-bitowa liczba całkowita ze znakiem ma miejsce na przechowywanie ponad 200 000 lat w mikrosekundach.

Możesz mieć wtedy

function microseconds() {
    $mt = explode(' ', microtime());
    return ((int)$mt[1]) * 1000000 + ((int)round($mt[0] * 1000000));
}

dlaczego nie tylko: `function getMilliEpoch () {$ mt = explode ('', microtime ()); zwróć $ mt [1]. substr ($ mt [0], 0, 5) * 1000; } `
Michael

Teraz jest parametr dla funkcji mikrotime, jeśli jest ustawiony na true, zwraca sekundy i milisekundy od 1 stycznia 1970 roku, 0 godzin 0 minut 0 sekund jako liczba zmiennoprzecinkowa. Oto przykład: microtime (true) // 1553260455.7242
kukko

@kukko tak, ale ze względu na ograniczoną precyzję typu float, obliczenie liczby milisekund z mikrotime (true) spowoduje nieco niedokładną wartość
Paolo

42

Jak inni stwierdzili, możesz użyć, microtime()aby uzyskać milisekundową precyzję na znacznikach czasu.

Z twoich komentarzy wydaje się, że chcesz, aby był to precyzyjny znacznik czasu UNIX. Coś jak DateTime.Now.Ticksw świecie .NET.

Aby to zrobić, możesz użyć następującej funkcji:

function millitime() {
  $microtime = microtime();
  $comps = explode(' ', $microtime);

  // Note: Using a string here to prevent loss of precision
  // in case of "overflow" (PHP converts it to a double)
  return sprintf('%d%03d', $comps[1], $comps[0] * 1000);
}

To jest sposób na zrobienie tego!
tonix

1
perrrrrrrfect .. ♥.
SRB zakazuje

Czy to nie zwraca czasu serwera? W moim przypadku czas przechowywany w db to czas mojej lokalnej przeglądarki. Załóżmy, że moja strefa czasowa zerowania to EST + 3, a czas mojej przeglądarki to GMT + 6. Gdy przesyłam formularz z lokalizacji GMT + 6, widzę, że przechowywany czas to GMT + 6 ekwiwalentu czasu w milisekundach. Więc jaki jest problem? :(
Zenith,

12

Użyj microtime(true)w PHP 5 lub następującą modyfikację w PHP 4:

array_sum(explode(' ', microtime()));

Przenośnym sposobem na napisanie tego kodu byłoby:

function getMicrotime()
{
    if (version_compare(PHP_VERSION, '5.0.0', '<'))
    {
        return array_sum(explode(' ', microtime()));
    }

    return microtime(true);
}

11

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

wynik:

2016-11-19 15:12:34.346351


1
Używa tego samego znacznika czasu:$t = gettimeofday(); echo date('Y-m-d H:i:s.',$t['sec']) . $t['usec'];
Savvas Radevic

mikrosekundy powinny być zerowane:$timeofday=gettimeofday(); echo sprintf("%s.%06d", date('Y-m-d H:i:s', $timeofday['sec']), $timeofday['usec']);
mabi

7

Spróbuj tego:

public function getTimeToMicroseconds() {
    $t = microtime(true);
    $micro = sprintf("%06d", ($t - floor($t)) * 1000000);
    $d = new DateTime(date('Y-m-d H:i:s.' . $micro, $t));

    return $d->format("Y-m-d H:i:s.u"); 
}

6

Działa to nawet jeśli korzystasz z 32-bitowego PHP:

list($msec, $sec) = explode(' ', microtime());

$time_milli = $sec.substr($msec, 2, 3); // '1491536422147'
$time_micro = $sec.substr($msec, 2, 6); // '1491536422147300'

Zauważ, że nie daje to liczb całkowitych, ale ciągi znaków. Jednak działa to dobrze w wielu przypadkach, na przykład podczas budowania adresów URL dla żądań REST.


Jeśli potrzebujesz liczb całkowitych, 64-bitowy PHP jest obowiązkowy.

Następnie możesz ponownie użyć powyższego kodu i przesłać do (int):

list($msec, $sec) = explode(' ', microtime());

// these parentheses are mandatory otherwise the precedence is wrong!
//                  ↓                        ↓
$time_milli = (int) ($sec.substr($msec, 2, 3)); // 1491536422147
$time_micro = (int) ($sec.substr($msec, 2, 6)); // 1491536422147300

Lub możesz użyć dobrych, jednowarstwowych:

$time_milli = (int) round(microtime(true) * 1000);    // 1491536422147
$time_micro = (int) round(microtime(true) * 1000000); // 1491536422147300

5
$timeparts = explode(" ",microtime());
$currenttime = bcadd(($timeparts[0]*1000),bcmul($timeparts[1],1000));
echo $currenttime;

UWAGA: PHP5 jest wymagane dla tej funkcji ze względu na ulepszenia w microtime () i moduł matematyki bc jest również wymagany (ponieważ mamy do czynienia z dużymi liczbami, możesz sprawdzić, czy masz moduł w phpinfo).

Mam nadzieję, że ci to pomoże.


5
$the_date_time = new DateTime($date_string);
$the_date_time_in_ms = ($the_date_time->format('U') * 1000) +
    ($the_date_time->format('u') / 1000);

Czy to tak naprawdę, jak dopełnienie trzech zer po prawej stronie?
Zeeshan,

Ani trochę. Konwertuje obie części na milisekundy i podaje sumę. Jest więc dokładniejszy niż dodawanie zer.
user3767296,

1
Ten fragment kodu może rozwiązać pytanie, ale wyjaśnienie naprawdę pomaga poprawić jakość posta. Pamiętaj, że w przyszłości odpowiadasz na pytanie dla czytelników, a ci ludzie mogą nie znać przyczyn Twojej sugestii kodu. Staraj się również nie tłoczyć kodu objaśniającymi komentarzami, co zmniejsza czytelność zarówno kodu, jak i objaśnień!
Michał Perłakowski


-2

Użyj tego:

function get_millis(){
  list($usec, $sec) = explode(' ', microtime());
  return (int) ((int) $sec * 1000 + ((float) $usec * 1000));
}

PA

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.