Bagaimana cara mendapatkan waktu saat ini sebagai bilangan bulat 13 digit di Ruby?

88

Saya memiliki jQueryfungsi ini yang mengembalikan waktu saat ini sebagai jumlah milidetik sejak periode (1 Jan 1970):

time = new Date().getTime();

Apakah ada cara untuk melakukan hal yang sama di Ruby?

Saat ini, saya menggunakan Ruby Time.now.to_iyang berfungsi dengan baik tetapi mengembalikan 10 digit integer (jumlah detik)

Bagaimana saya bisa membuatnya menampilkan jumlah milidetik, seperti dalam jQuery?

Tintin81
sumber
5
Itu bukan "fungsi jQuery", itu hanya ECMAScript (javascript) biasa. Mungkin itulah yang mendorong -1, meskipun agak kasar.
RobG
Lihat juga stackoverflow.com/q/20001883/238886
Wayne Conrad

Jawaban:

155
require 'date'

p DateTime.now.strftime('%s') # "1384526946" (seconds)
p DateTime.now.strftime('%Q') # "1384526946523" (milliseconds)
steenslag.dll
sumber
31
Catatan untuk pengguna Rails: strftimemetode yang disediakan ActiveSupport::TimeWithZonetidak termasuk %sdan %Qpenentu. Anda harus mengonversi ke Ruby biasa DateTimeterlebih dahulu, menggunakan to_datetimemetode ini.
Lonnon Foster
6
@LonnonFoster Sekarang berfungsi (baru saja diuji di konsol Rails).
Nikola Stojaković
Hai, bagaimana saya bisa melakukan hal yang sama, tetapi tidak untuk saat ini, melainkan dari bidang tanggal?
Tomer
Perhatikan bahwa ini memotong daripada membulatkan (seperti yang Anda lihat dari contoh - 1384526946523ms harus dibulatkan menjadi 1384526947s).
David Moles
102

Javascript gettime()mengembalikan jumlah milidetik sejak periode.

Ruby Time.now.to_iakan memberi Anda jumlah detik sejak epoch. Jika Anda mengubahnya menjadi Time.now.to_f, Anda masih mendapatkan detik tetapi dengan komponen pecahan. Kalikan saja dengan 1.000 dan Anda mendapatkan milidetik. Kemudian gunakan #to_iuntuk mengubahnya menjadi integer. Dan Anda berakhir dengan:

(Time.now.to_f * 1000).to_i
Anthony DeSimone
sumber
Terima kasih banyak atas penjelasannya! Masih baru untuk semua ini ... Tidak tahu jawaban mana yang harus ditandai sebagai yang benar sebenarnya ...
Tintin81
1
Sekadar informasi lebih lanjut, Time.nowberasal dari Ruby karena Time.currentberasal dari Rails. Demikianlah Time.currentyang diakui oleh zona waktu aplikasi Rails dan Time.nowmenggunakan zona waktu server. Dalam pengalaman saya, selalu gunakan Time.currentpada aplikasi Rails Anda untuk konsistensi zona waktu
vutran
1
Tidak, Anda tidak boleh menggunakan Time.currentdi sini sama sekali, membutuhkan waktu lebih lama untuk membuatnya, dan karena Anda segera mengubahnya menjadi stempel waktu unix, Anda sama sekali tidak peduli dengan konsistensi zona waktu. (Stempel waktu Unix selalu berhubungan dengan UTC). Jadi, sementara apa yang Anda katakan benar dalam 99% kasus, yang satu ini dari segi kinerja turun di 1% terakhir.
The Pellmeister
1
Ini adalah pendekatan pilihan saya. Satu hal yang ingin saya lakukan adalah menambah kelas Waktu untuk menambahkan :epochmetode: kelas Waktu def epoch (self.to_f * 1000). To_i end end
Matt Welke
@brauliobo Mau jelaskan bagaimana cara memalsukan milidetik? Pernyataan Anda menyesatkan, jawaban OP benar sekali.
coisnepe
31

(Time.now.to_f * 1000).to_i harus melakukan hal yang sama.

Zach Kemp
sumber
1
@brauliobo apa milidetik palsu?
Erik Rothoff
1
@brauliobo Ini tidak, karena to_fmenyertakan milidetik sebagai desimal.
CashIsClay
21

Dengan menggunakan strftime, Anda bisa mendapatkan jumlah detik dan menambahkan milidetik pecahan (atau unit yang lebih kecil, jika perlu):

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

Perhatikan bahwa ini tidak bulat, ini terpotong, seperti yang Anda lihat dengan to_fatau jika Anda keluar ke mikrodetik:

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

dan to_f/ to_isolusi memiliki masalah yang sama:

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

jadi jika Anda benar-benar peduli dengan akurasi milidetik, taruhan yang lebih baik mungkin to_fdengan round:

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

Yang mengatakan, seperti yang dicatat dalam dokumen , "IEEE 754 double tidak cukup akurat untuk mewakili jumlah nanodetik sejak Epoch", jadi jika Anda benar- benar peduli, pertimbangkan to_rdaripada to_f-

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

- meskipun jika Anda hanya membulatkan ke milidetik Anda mungkin baik-baik saja.

David Moles
sumber
18

Hati-hati, jangan bingung. Fakta bahwa Ruby mendukung gagasan pecahan detik sebagai pelampung sebenarnya tidak menjadikannya sebagai bilangan floating point. Saya mendapat masalah dengan ini ketika saya melakukan perbandingan waktu cap waktu Wireshark dengan Python ... perhitungan waktu di pcap-ng tidak berfungsi. Hanya ketika saya memperlakukan dua bagian (detik integral dan nanodetik integral) karena kedua bilangan bulat saya bisa mendapatkan angka yang tepat.

Itu karena angka floating point memiliki masalah Akurasi . Memang, sedikit Ruby akan menunjukkan kepada Anda bahwa to_f tidak sama, katakanlah, 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. Anda mungkin aman untuk 3 digit signifikan, tetapi faktanya tetap: Angka floating point di komputer adalah perkiraan. Penghitung nanodetik pada komputer modern adalah bilangan bulat.

Mike S.
sumber
Respon yang lebih baik. Terima kasih. Format direktif .strftime("%9N")juga bisa digunakan. ruby-doc.org/core-2.3.1/Time.html#method-i-strftime
rplaurindo
13

Dapatkan objek Waktu dengan Time.now, memanggil #to_imengembalikan stempel waktu Unix (detik dari epoch). #to_fmemberikan pecahan detik yang dapat Anda gunakan untuk mendapatkan milidetik dari epoch:

Time.now.to_f * 1000
levinalex.dll
sumber
3
ini palsu dalam milidetik
brauliobo
@brauliobo Bagaimana "milidetik palsu" ini? Apakah Anda meluangkan waktu untuk mengeksekusi kode dan memeriksanya sendiri?
coisnepe
0

Typecast Integer (1e6 * Time.now.to_f) mengembalikan Bignum yang dapat menahan milidetik

chava
sumber