Nanosekundy na datę
Konwertuj nanosekundy na czytelną datę. Wprowadź znacznik czasu w nanosekundach (np. 1704067200000000000).
Znacznik czasu w nanosekundach po cichu traci trzy ostatnie cyfry w liczbie JavaScriptu
Liczby w JavaScripcie przechowują liczby całkowite dokładnie tylko do 2⁵³ − 1. Bieżący znacznik czasu w nanosekundach to około 1,77 × 10¹⁸, czyli 196 razy powyżej tej granicy. Podaj go, a 1770000000123456789 wróci jako 1770000000123456800 — bez błędu, bez ostrzeżenia, po prostu trzy cyfry cicho podmienione.
Jak to działa
- Przelicza znaczniki czasu w nanosekundach na daty i z powrotem, zachowując część poniżej milisekundy.
- Sygnalizuje granicę precyzji, bo ta awaria jest cicha, a nie głośna.
- Obsługuje przeliczenie na milisekundy, których większość bibliotek dat wymaga na wejściu.
nanosekundy ÷ 1 000 000 = milisekundy nanosekundy ÷ 1 000 000 000 = sekundy MAX_SAFE_INTEGER = 9 007 199 254 740 991 (2⁵³ − 1) w nanosekundach cały ten zakres obejmuje tylko około 104 dni w milisekundach obejmuje około 285 000 lat
Przykład z liczbami
Ile czasu daje każda jednostka wewnątrz bezpiecznego zakresu liczb całkowitych i co dzieje się po jego przekroczeniu.
- milisekundy: 2⁵³ obejmuje około 285 000 lat
- mikrosekundy: około 285 lat
- nanosekundy: około 0,285 roku — mniej więcej 104 dni
- 1770000000123456789 przypisane do liczby
- odczytuje się z powrotem jako 1770000000123456800
Trzy ostatnie cyfry się zmieniły i nic tego nie zgłosiło. Znacznik czasu w nanosekundach wymaga BigInt albo ciągu znaków; trzymanie go w zwykłej liczbie to nie niedogodność zaokrąglenia, tylko gwarancja, że szczegół poniżej mikrosekundy jest fikcją.
Jak czytać wynik
- Do arytmetyki nanosekundowej używaj BigInt i przechodź na zwykłą liczbę dopiero po podzieleniu w dół do milisekund. Dzielenie musi odbyć się w przestrzeni BigInt — konwersja najpierw, a dzielenie potem, już zniszczyła cyfry, które próbowałeś zachować.
- Bazy danych i formaty transmisji często niosą nanosekundy jako ciągi znaków dokładnie z tego powodu. Sparsowanie takiego ciągu do liczby zmiennoprzecinkowej, żeby go „uporządkować”, to najczęstszy sposób utraty precyzji, a dzieje się to w warstwie, której nikt nie ogląda.
- Sam obiekt Date w JavaScripcie opiera się na milisekundach i w ogóle nie potrafi reprezentować czasu poniżej milisekundy. Konwersja nanosekund na Date odrzuca resztę z założenia, więc ta strata jest oczekiwana, a nie błędna — zaskoczeniem jest wyłącznie sytuacja, gdy dzieje się to po cichu w trakcie obliczeń.
- Precyzja nanosekundowa rzadko jest rzeczywistym wymaganiem. Porządkowanie logów, śledzenie i profilowanie zwykle potrzebują monotonicznej kolejności, a nie bezwzględnej dokładności nanosekundowej, a zegar monotoniczny daje to bez problemu z reprezentacją.
Częste pytania
- Dlaczego mój znacznik czasu zmienił się o kilkaset nanosekund?
- Bo trafił do liczby zmiennoprzecinkowej, która nie potrafi go przedstawić. Powyżej 2⁵³ − 1 liczby całkowite zaokrągla się do najbliższej reprezentowalnej wartości, więc 1770000000123456789 staje się 1770000000123456800. Nic nie zgłasza błędu, bo to zachowanie zdefiniowane, a nie usterka.
- Jak przechowywać znaczniki czasu w nanosekundach?
- Jako BigInt w JavaScripcie, jako 64-bitową liczbę całkowitą w większości innych języków albo jako ciąg znaków przy przekraczaniu granicy takiej jak JSON. Na zwykłą liczbę przechodź dopiero po podzieleniu w dół do milisekund, gdy dodatkowe cyfry przestają być potrzebne.