Как получить текущее время как 13-значное целое число в Ruby?

88

У меня есть эта jQueryфункция, которая возвращает текущее время как количество миллисекунд с эпохи (1 января 1970 г.):

time = new Date().getTime();

Есть ли способ сделать то же самое в Ruby?

Прямо сейчас я использую Ruby, Time.now.to_iкоторый отлично работает, но возвращает 10-значное целое число (количество секунд).

Как я могу заставить его отображать количество миллисекунд, как в jQuery?

Тинтин81
источник
5
Это не «функция jQuery», это просто ECMAScript (javascript). Возможно, именно это и вызвало -1, хотя и немного резковато.
RobG
См. Также stackoverflow.com/q/20001883/238886
Уэйн Конрад,

Ответы:

151
require 'date'

p DateTime.now.strftime('%s') # "1384526946" (seconds)
p DateTime.now.strftime('%Q') # "1384526946523" (milliseconds)
Steenslag
источник
31
Примечание для пользователей Rails: strftimeметод , предоставляемый ActiveSupport::TimeWithZoneне включает %sи %Qопределители. DateTimeСначала вам нужно преобразовать в простой Ruby , используя to_datetimeметод.
Лоннон Фостер
6
@LonnonFoster Теперь он работает (только что протестирован в консоли Rails).
Никола Стоякович
Привет, как я могу сделать то же самое, но не сейчас, а из поля даты?
Томер
Нашел это здесь: stackoverflow.com/questions/24149463/ruby-strftimeq-broken
Томер
101

Javascript gettime()возвращает количество миллисекунд с начала эпохи.

Ruby Time.now.to_iдаст вам количество секунд с начала эпохи. Если вы измените это значение на Time.now.to_f, вы все равно получите секунды, но с дробной составляющей. Просто умножьте это на 1000, и вы получите миллисекунды. Затем используйте, #to_iчтобы преобразовать его в целое число. И вы получите:

(Time.now.to_f * 1000).to_i
Энтони ДеСимоун
источник
Большое спасибо за объяснение! Все еще новичок во всем этом ... Не знаю, какой ответ на самом деле отметить как правильный ...
Tintin81
1
Для получения дополнительной информации, Time.nowпроисходит от Ruby, поскольку Time.currentпроисходит от Rails. Таким образом Time.current, распознается часовой пояс приложения Rails и Time.nowиспользуется часовой пояс сервера. По моему опыту, всегда используйте Time.currentв своем приложении Rails для согласованности часовых
поясов
1
Нет, вам вообще не следует использовать Time.currentздесь, это требует больше времени для построения, и, поскольку вы сразу конвертируете его в метку времени unix, вас вообще не заботит согласованность часовых поясов. (Временные метки Unix всегда относятся к UTC). Итак, хотя то, что вы говорите, верно в 99% случаев, этот показатель с точки зрения производительности падает в последнем 1%.
The Pellmeister
1
Это мой предпочтительный подход. Одна вещь, которую я люблю делать, - это :epochрасширять класс Time, добавляя метод: class Time def epoch (self.to_f * 1000) .to_i end end
Мэтт
1
это подделывает миллисекунды
brauliobo
31

(Time.now.to_f * 1000).to_i должен делать то же самое.

Зак Кемп
источник
1
@brauliobo, что за фальшивые миллисекунды?
Эрик Ротофф
1
@brauliobo Это не так, поскольку to_fмиллисекунды являются десятичными.
CashIsClay
20

Используя strftime, вы можете получить количество секунд и добавить дробные миллисекунды (или меньшие единицы, если необходимо):

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

Обратите внимание, что это не округляется, а обрезается, как вы можете видеть с помощью to_fили, если вы выходите на микросекунды:

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

и решение to_f/ to_iимеет ту же проблему:

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

так что если вы действительно заботитесь о миллисекунды точности, лучше ставка может быть to_fс round:

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

Тем не менее, как отмечено в документации , «IEEE 754 double недостаточно точен для представления количества наносекунд с эпохи», поэтому, если вам действительно все равно, подумайте to_rвместо to_f-

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

- хотя, если вы округляете только до миллисекунд, вы, вероятно, в порядке.

Дэвид Молес
источник
18

Будьте осторожны, не запутайтесь. Тот факт, что Ruby поддерживает идею дробных секунд как числа с плавающей запятой, на самом деле не делает их числом с плавающей запятой. У меня возникли проблемы с этим, когда я проводил сравнение временных меток Wireshark в Python ... вычисления времени в pcap-ng просто не работали. Только когда я обработал две части (целые секунды и целые наносекунды) как оба целых числа, я смог получить правильные числа.

Это потому, что числа с плавающей запятой имеют проблемы с точностью . Действительно, небольшой кусочек Ruby покажет вам, что to_f не равно, скажем, 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

Будьте программистом. Вы можете быть уверены в трех значащих цифрах, но факт остается фактом: числа с плавающей запятой на компьютерах являются приблизительными. Счетчики наносекунд на современных компьютерах являются целыми числами.

Майк С
источник
Лучший ответ. Спасибо. .strftime("%9N")Также можно использовать формат директивы . ruby-doc.org/core-2.3.1/Time.html#method-i-strftime
rplaurindo
13

Получить объект Time с помощью Time.now, вызов #to_iвозвращает отметку времени Unix (секунды от эпохи). #to_fдает дробные секунды, которые вы можете использовать для получения миллисекунд от эпохи:

Time.now.to_f * 1000
левиналекс
источник
3
это подделывает миллисекунды
brauliobo
0

Целое число с приведением типов (1e6 * Time.now.to_f) возвращает Bignum, который может содержать миллисекунды.

хава
источник