tl; dr. Użyj microtime(false) i przechowuj wyniki w bigint MySQL jako milionowe części sekundy. W przeciwnym razie musisz nauczyć się wszystkiego o arytmetyce zmiennoprzecinkowej, która jest wielką, grubą kulą włosową.
Funkcja mikroczasu PHP pobiera uniksowy znacznik czasu (obecnie około szesnastkowy 50eb7c00 lub dziesiętny 1.357.609.984) z jednego wywołania systemowego oraz czas w mikrosekundach z innego wywołania systemowego. Następnie przekształca je w ciąg znaków. Następnie, jeśli wywołasz to z (true), konwertuje tę liczbę na 64-bitową liczbę zmiennoprzecinkową IEEE 745, coś, co PHP nazywa float
.
Na dzień dzisiejszy potrzebujesz dziesięciu cyfr dziesiętnych z lewej strony przecinka, aby zapisać całkowity znacznik czasu UNIX. Pozostanie to prawdą do około 2280 roku n.e., kiedy twoi potomkowie zaczną potrzebować jedenastu cyfr. Potrzebujesz sześciu cyfr z prawej strony miejsca dziesiętnego, aby zapisać mikrosekundy.
Nie uzyskasz całkowitej dokładności w mikrosekundach. Większość systemów utrzymuje zegar systemowy poniżej sekundy z rozdzielczością w zakresie 1-33 milisekund. To zależy od systemu.
MySQL w wersji 5.6.4 i nowszych pozwala na określenie DATETIME(6)
kolumn, w których będą przechowywane daty i godziny z dokładnością do mikrosekund. Jeśli używasz takiej wersji MySQL, jest to absolutna droga.
Przed wersją 5.6.4 musisz użyć MySQL DOUBLE
(IEEE 754 64-bitowa liczba zmiennoprzecinkowa) do przechowywania tych liczb. MySQL FLOAT
(IEEE 754 32-bitowa liczba zmiennoprzecinkowa) nie ma wystarczającej liczby bitów w swojej mantysie, aby całkowicie dokładnie przechowywać nawet aktualny czas UNIX w sekundach.
Dlaczego przechowujesz te sygnatury czasowe? Czy masz nadzieję to zrobić
WHERE table.timestamp = 1357609984.100000
lub podobne zapytania w celu wyszukania określonych pozycji? Jest to niebezpieczne, jeśli użyjesz liczb zmiennoprzecinkowych lub podwójnych w dowolnym miejscu łańcucha przetwarzania (to znaczy, nawet jeśli używasz microtime(true)
nawet raz). Są znani z tego, że nie są równi, nawet jeśli myślałeś, że powinni. Zamiast tego musisz użyć czegoś takiego. 0.001
Nazywa się „epsilon” w branży przetwarzania numerycznego.
WHERE table.timestamp BETWEEN 1357609984.100000 - 0.001
AND 1357609984.100000 + 0.001
lub coś podobnego. Nie będziesz miał tego problemu, jeśli przechowujesz te znaczniki czasu jako ułamki dziesiętne lub w milionowych częściach sekundy w bigint
kolumna.
64-bitowy zmiennoprzecinkowy IEEE ma 53 bity mantysy -- precyzji. Obecny znacznik czasu UNIX Epoch (sekundy od 1 stycznia 1970 r. 00:00Z) pomnożony przez milion wykorzystuje 51 bitów. Tak więc w DOUBLE nie ma zbyt wiele dodatkowej precyzji, jeśli zależy nam na bitach niskiego rzędu. Z drugiej strony precyzja nie wyczerpie się przez kilka stuleci.
Dzięki int64(BIGINT) nigdzie nie zabraknie Ci precyzji. Gdybym faktycznie przechowywał mikrosekundowe znaczniki czasu tylko w celu ich uporządkowania w MySQL, wybrałbym DATETIME(6)
ponieważ dostałbym dużo arytmetyki dat za darmo. Gdybym robił aplikację o dużej objętości w pamięci, użyłbym int64.