Comment obtenir l'heure actuelle sous forme d'entier à 13 chiffres en Ruby?

88

J'ai cette jQueryfonction qui renvoie l'heure actuelle sous forme de nombre de millisecondes depuis l'époque (1er janvier 1970):

time = new Date().getTime();

Existe-t-il un moyen de faire la même chose dans Ruby?

En ce moment, j'utilise Ruby Time.now.to_iqui fonctionne très bien mais renvoie un entier à 10 chiffres (nombre de secondes)

Comment puis-je lui faire afficher le nombre de millisecondes, comme dans jQuery?

Tintin81
la source
5
Ce n'est pas une "fonction jQuery", c'est juste ECMAScript (javascript). C'est peut-être ce qui a incité le -1, un peu dur cependant.
RobG
Voir aussi stackoverflow.com/q/20001883/238886
Wayne Conrad

Réponses:

151
require 'date'

p DateTime.now.strftime('%s') # "1384526946" (seconds)
p DateTime.now.strftime('%Q') # "1384526946523" (milliseconds)
Steenslag
la source
31
Remarque pour les utilisateurs de Rails: la strftimeméthode fournie par ActiveSupport::TimeWithZonen'inclut pas les spécificateurs %set %Q. Vous devrez d'abord convertir en un Ruby simple DateTime, en utilisant la to_datetimeméthode.
Lonnon Foster
6
@LonnonFoster Maintenant ça marche (juste testé dans la console Rails).
Nikola Stojaković
Salut, comment puis-je faire la même chose, mais pas pour le moment, mais plutôt à partir d'un champ de date?
Tomer
101

Javascript gettime()renvoie le nombre de millisecondes depuis l'époque.

Ruby's Time.now.to_ivous donnera le nombre de secondes depuis l'époque. Si vous changez cela en Time.now.to_f, vous obtenez toujours des secondes mais avec un composant fractionnaire. Multipliez simplement cela par 1000 et vous avez des millisecondes. Puis utilisez #to_ipour le convertir en entier. Et vous vous retrouvez avec:

(Time.now.to_f * 1000).to_i
Anthony DeSimone
la source
Merci beaucoup pour l'explication! Encore nouveau dans tout cela ... Je ne sais pas quelle réponse marquer comme la bonne en fait ...
Tintin81
1
Juste pour plus d'informations, Time.nowvient de Ruby puisque Time.currentvient de Rails. Ainsi Time.currentest reconnu par le fuseau horaire de l'application Rails et Time.nowutilise le fuseau horaire du serveur. D'après mon expérience, utilisez toujours Time.currentvotre application Rails pour la cohérence du fuseau horaire
vutran
1
Non, vous ne devriez pas du tout utiliser Time.currentici, cela prend plus de temps à construire, et comme vous le convertissez immédiatement en un horodatage unix, vous ne vous souciez pas du tout de la cohérence du fuseau horaire. (Les horodatages Unix se rapportent toujours à UTC). Donc, alors que ce que vous dites est vrai dans 99% des cas, celui-ci en termes de performances tombe dans le dernier 1%.
The Pellmeister
1
C'est mon approche préférée. Une chose que j'aime faire est d'augmenter la classe Time pour ajouter une :epochméthode: class Time def epoch (self.to_f * 1000) .to_i end end
Matt Welke
1
cela
simule
31

(Time.now.to_f * 1000).to_i devrait faire la même chose.

Zach Kemp
la source
1
@brauliobo qu'est-ce que les fausses millisecondes?
Erik Rothoff
1
@brauliobo Ce n'est pas le cas, car il to_finclut les millisecondes sous forme de décimale.
CashIsClay
20

En utilisant strftime, vous pouvez obtenir le nombre de secondes et ajouter des fractions de millisecondes (ou des unités plus petites, si nécessaire):

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

Notez cependant que cela ne s'arrondit pas, il tronque, comme vous pouvez le voir avec to_fou si vous sortez en microsecondes:

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

et la solution to_f/ to_ia le même problème:

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

donc si vous vous souciez vraiment de la précision à la milliseconde, un meilleur pari peut être to_favec round:

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

Cela dit, comme indiqué dans la documentation , "IEEE 754 double n'est pas assez précis pour représenter le nombre de nanosecondes depuis l'époque", donc si vous vous en souciez vraiment , considérez to_rau lieu de to_f-

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

- bien que si vous arrondissez seulement aux millisecondes, vous allez probablement bien.

David Moles
la source
18

Soyez prudent, ne soyez pas confus. Le fait que Ruby prenne en charge l'idée des fractions de seconde comme flottant n'en fait pas réellement un nombre à virgule flottante. J'ai eu des problèmes avec cela quand je faisais des comparaisons de temps d'horodatage Wireshark en Python ... les calculs de temps dans le pcap-ng ne fonctionnaient tout simplement pas. Ce n'est que lorsque j'ai traité les deux parties (secondes intégrales et nanosecondes intégrales) car les deux entiers que j'ai pu obtenir des nombres appropriés.

C'est parce que les nombres à virgule flottante ont des problèmes de précision . En effet, un petit bout de Ruby vous montrera que to_f n'est pas égal, disons, 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

Programmeur d'avertissement. Vous pouvez être sûr de 3 chiffres significatifs, mais le fait demeure: les nombres à virgule flottante sur les ordinateurs sont des approximations. Les compteurs nanosecondes des ordinateurs modernes sont des nombres entiers.

Mike S
la source
La meilleure réponse. Merci. Le format de directive .strftime("%9N")peut également être utilisé. ruby-doc.org/core-2.3.1/Time.html#method-i-strftime
rplaurindo
13

Obtenir un objet Time avec Time.now, appeler #to_irenvoie un horodatage Unix (secondes à partir de l'époque). #to_fdonne des fractions de seconde que vous pouvez utiliser pour obtenir des millisecondes à partir de l'époque:

Time.now.to_f * 1000
levinalex
la source
3
cela
simule
0

Le type Integer (1e6 * Time.now.to_f) renvoie un Bignum qui peut contenir les millisecondes

chava
la source