Jak uzyskać bieżący czas jako 13-cyfrową liczbę całkowitą w Rubim?

88

Mam tę jQueryfunkcję, która zwraca bieżący czas jako liczbę milisekund od epoki (1 stycznia 1970):

time = new Date().getTime();

Czy jest sposób, aby zrobić to samo w Rubim?

W tej chwili używam Rubiego, Time.now.to_iktóry działa świetnie, ale zwraca 10-cyfrową liczbę całkowitą (liczbę sekund)

Jak mogę sprawić, aby wyświetlał liczbę milisekund, tak jak w jQuery?

Tintin81
źródło
5
To nie jest „funkcja jQuery”, to po prostu zwykły ECMAScript (javascript). Być może to właśnie spowodowało -1, choć nieco szorstki.
RobG
Zobacz także stackoverflow.com/q/20001883/238886
Wayne Conrad

Odpowiedzi:

151
require 'date'

p DateTime.now.strftime('%s') # "1384526946" (seconds)
p DateTime.now.strftime('%Q') # "1384526946523" (milliseconds)
steenslag
źródło
31
Uwaga dla użytkowników Railsów: strftimemetoda dostarczona przez ActiveSupport::TimeWithZonenie zawiera specyfikatorów %si %Q. DateTimeNajpierw musisz przekonwertować na zwykły Ruby , używając tej to_datetimemetody.
Lonnon Foster
6
@LonnonFoster Teraz to działa (właśnie przetestowane w konsoli Rails).
Nikola Stojaković
Cześć, jak mogę zrobić to samo, ale nie teraz, ale raczej z pola daty?
Tomer
101

JavaScript gettime()zwraca liczbę milisekund od epoki.

Ruby Time.now.to_ipoda liczbę sekund od epoki. Jeśli zmienisz to na Time.now.to_f, nadal otrzymasz sekundy, ale z ułamkowym składnikiem. Po prostu pomnóż to przez 1000 i masz milisekundy. Następnie użyj, #to_iaby przekonwertować go na liczbę całkowitą. Otrzymujesz:

(Time.now.to_f * 1000).to_i
Anthony DeSimone
źródło
Wielkie dzięki za wyjaśnienie! Wciąż nowy w tej całej sprawie ... Nie wiem, którą odpowiedź oznaczyć jako właściwą ...
Tintin81
1
Aby uzyskać więcej informacji, Time.nowpochodzi od Rubiego, ponieważ Time.currentpochodzi z Railsów. Tak więc Time.currentjest to potwierdzane przez strefę czasową aplikacji Railsów i Time.nowużywa strefy czasowej serwera. Z mojego doświadczenia, zawsze używać Time.currentod aplikacji Rails dla spójności czasowej
vutran
1
Nie, w ogóle nie powinieneś używać Time.currenttutaj, konstruowanie zajmuje więcej czasu, a ponieważ natychmiast konwertujesz go na uniksowy znacznik czasu, nie przejmujesz się w ogóle spójnością strefy czasowej. (Znaczniki czasu systemu Unix zawsze odnoszą się do czasu UTC). Tak więc, chociaż to, co mówisz, jest prawdą w 99% przypadków, ten pod względem wydajności przypada na ostatni 1%.
The Pellmeister
1
To jest moje preferowane podejście. Jedną z rzeczy, które lubię robić, jest rozszerzenie klasy Time, aby dodać :epochmetodę: class Time def epoch (self.to_f * 1000) .to_i end end
Matt Welke
1
to
udaje
31

(Time.now.to_f * 1000).to_i powinien zrobić to samo.

Zach Kemp
źródło
1
@brauliobo co to są fałszywe milisekundy?
Erik Rothoff,
1
@brauliobo Nie, ponieważ to_fzawiera milisekundy jako ułamek dziesiętny.
CashIsClay
20

Używając strftime, możesz uzyskać liczbę sekund i dołączyć ułamkowe milisekundy (lub mniejsze jednostki, jeśli to konieczne):

2.2.2 :001 > t = Time.new
 => 2015-06-02 12:16:56 -0700 
2.2.2 :002 > t.strftime('%s%3N')
 => "1433272616888" 

Zwróć jednak uwagę, że to nie zaokrągla, obcina, jak widać z to_flub jeśli wychodzisz do mikrosekund:

2.2.2 :003 > t.to_f
 => 1433272616.888615
2.2.2 :004 > t.usec
 => 888615 

a to_f/ to_irozwiązanie ma ten sam problem:

2.2.2 :009 > (t.to_f * 1000).to_i
 => 1433272616888

więc jeśli naprawdę dbają o milisekundy dokładność, lepszy zakład może być to_fz round:

2.2.2 :010 > (t.to_f * 1000).round
 => 1433272616889

To powiedziawszy, jak zauważono w dokumentach , „IEEE 754 double nie jest wystarczająco dokładny, aby przedstawić liczbę nanosekund od Epoki”, więc jeśli naprawdę cię to obchodzi, rozważ to_rzamiast to_f-

2.2.2 :011 > (t.to_r * 1000).round
 => 1433272616889 

- chociaż jeśli zaokrąglasz tylko do milisekund, prawdopodobnie jesteś w porządku.

David Moles
źródło
18

Uważaj, nie daj się zmylić. Fakt, że Ruby wspiera ideę ułamków sekund jako liczby zmiennoprzecinkowej, w rzeczywistości nie sprawia, że ​​jest to liczba zmiennoprzecinkowa. Wpadłem z tym w kłopoty, kiedy robiłem porównania czasu znaczników czasu Wireshark w Pythonie ... obliczenia czasu w pcap-ng po prostu nie działały. Dopiero gdy potraktowałem dwie części (całkowite sekundy i całkowite nanosekundy) jako obie liczby całkowite, byłem w stanie uzyskać odpowiednie liczby.

Dzieje się tak, ponieważ liczby zmiennoprzecinkowe mają problemy z dokładnością . Rzeczywiście, krótki fragment Rubiego pokaże ci, że to_f nie równa się, powiedzmy, nsec:

irb(main):019:0> t=Time.now
=> 2015-04-10 16:41:35 -0500
irb(main):020:0> puts "#{t.to_f}; #{t.nsec}"
1428702095.1435847; 143584844

Caveat Programmer. Możesz być bezpieczny do 3 cyfr znaczących, ale fakt pozostaje: Liczby zmiennoprzecinkowe na komputerach są przybliżeniami. Liczniki nanosekund na nowoczesnych komputerach to liczby całkowite.

Mike S.
źródło
Lepsza odpowiedź. Dziękuję Ci. Można .strftime("%9N")również użyć formatu dyrektywy . ruby-doc.org/core-2.3.1/Time.html#method-i-strftime
rplaurindo
13

Pobierz obiekt Time za pomocą Time.now, wywołanie #to_izwraca uniksowy znacznik czasu (sekundy od epoki). #to_fdaje ułamkowe sekundy, których możesz użyć, aby uzyskać milisekundy z epoki:

Time.now.to_f * 1000
levinalex
źródło
3
to
udaje
0

Typecast Integer (1e6 * Time.now.to_f) zwraca Bignum, który może pomieścić milisekundy

chava
źródło