Как в Ruby узнать прошедшее время в миллисекундах?


99

Если у меня есть Timeобъект, полученный от:

Time.now

а позже я создаю другой объект с той же строкой, как я могу узнать, сколько миллисекунд прошло? Второй объект может быть создан в ту же минуту, в течение следующих минут или даже часов.

Ответы:


134

Как уже говорилось, вы можете работать с Timeобъектами, как если бы они были числовыми (или с плавающей запятой) значениями. Эти операции приводят к второму разрешению, которое можно легко преобразовать.

Например:

def time_diff_milli(start, finish)
   (finish - start) * 1000.0
end

t1 = Time.now
# arbitrary elapsed time
t2 = Time.now

msecs = time_diff_milli t1, t2

Вам нужно будет решить, обрезать это или нет.


2
добавьте to_i, и вы получите его как целое число, например: ((finish - start) * 1000.0) .to_i
Travis Reeder

finish.to_f - start.to_f?
bodacious

1
finish - startдает плавающую точку; .to_fбудет лишним.
ezpz

5
Если вы используете рельсы или активную поддержку, вы можете использовать метод #in_milliseconds для того же преобразования(t2 - t1).in_milliseconds
Натан Ханна,

59

Вы можете добавить немного синтаксического сахара к вышеуказанному решению следующим образом:

class Time
  def to_ms
    (self.to_f * 1000.0).to_i
  end
end

start_time = Time.now
sleep(3)
end_time = Time.now
elapsed_time = end_time.to_ms - start_time.to_ms  # => 3004

31

Думаю, ответ выбран неправильно, этот метод дает секунды, а не миллисекунды.

t = Time.now.t­o_f
=> 1382471965.146

Здесь я предполагаю, что плавающее значение - это миллисекунды.


1
Выбранный ответ правильный. Использование сложения или вычитания Time.nowозначает обработку времени как значений с плавающей запятой с секундами до десятичной точки и до наносекунд после десятичной точки (хотя нсек может быть не совсем точным). Таким образом, умножение этого значения на 1000.0дает миллисекунды.
dfherr

да, но просто "Time.now" неточно и не дает точного ответа на вопрос.
LowFieldTheory

12

Чтобы получить время в миллисекундах, лучше добавить .round(3), чтобы в некоторых случаях было точнее:

puts Time.now.to_f # => 1453402722.577573

(Time.now.to_f.round(3)*1000).to_i  # => 1453402722578

9

Ответ ezpz почти идеален, но я надеюсь, что смогу добавить еще немного.

Гео спросил о времени в миллисекундах; это звучит как целое число, и я бы не стал идти в обход с плавающей запятой. Таким образом, мой подход был бы следующим:

irb(main):038:0> t8 = Time.now
=> Sun Nov 01 15:18:04 +0100 2009
irb(main):039:0> t9 = Time.now
=> Sun Nov 01 15:18:18 +0100 2009
irb(main):040:0> dif = t9 - t8
=> 13.940166
irb(main):041:0> (1000 * dif).to_i
=> 13940

Умножение на целое число 1000 отлично сохраняет дробное число и может быть немного быстрее.

Если вы имеете дело с датой и временем, вам может потребоваться класс DateTime . Это работает аналогично, но коэффициент преобразования 24 * 3600 * 1000 = 86400000 .

Я нашел функции DateTime strptime и strftime бесценными при синтаксическом анализе и форматировании строк даты / времени (например, в / из журналов). Полезно знать следующее:

  • Символы форматирования для этих функций (% H,% M,% S, ...) почти такие же, как для функций C, имеющихся в любой системе Unix / Linux; и

  • Есть еще несколько: В частности, % L обрабатывает миллисекунды!


Хорошо знать! Спасибо unknown:)
Geo

1
В любом случае% L существует только в Ruby 1.9;)
Рафа де Кастро

7

%L дает миллисекунды в рубинах

require 'time'
puts Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L")

или

puts Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")

даст вам текущую временную метку в миллисекундах.


Здесь не сказано, как узнать истекшее время.
Роберт

7
DateTime.now.strftime("%Q")

Пример использования:

>> DateTime.now.strftime("%Q")
=> "1541433332357"

>> DateTime.now.strftime("%Q").to_i
=> 1541433332357

6

Time.now.to_f может вам помочь, но возвращает секунды.

В общем, при работе с тестами я:

  • поставить в переменную текущее время;
  • вставьте блок для проверки;
  • ввести в переменную текущее время, вычитая предыдущее значение текущего времени;

Это очень простой процесс, поэтому я не уверен, что вы действительно об этом спрашивали ...


4

Ответ примерно такой:

t_start = Time.now
# time-consuming operation
t_end = Time.now

milliseconds = (t_start - t_end) * 1000.0

Однако Time.nowподход рискует оказаться неточным. Я нашел этот пост Луки Гуиди:

https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/

системные часы постоянно плавают и движутся не только вперед. Если ваш расчет прошедшего времени основан на нем, вы, скорее всего, столкнетесь с ошибками в расчетах или даже с простоями .

Поэтому рекомендуется использовать Process.clock_gettimeвместо него. Что-то вроде:

def measure_time
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  yield
  end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  elapsed_time = end_time - start_time
  elapsed_time.round(3)
end

Пример:

elapsed = measure_time do
    # your time-consuming task here:
    sleep 2.2321
end

=> 2.232

3

Попробуйте вычесть первое Time.now из второго. Вот так:

a = Time.now
sleep(3)
puts Time.now - a # about 3.0

Это дает вам число секунд с плавающей запятой между двумя моментами времени (а вместе с тем и миллисекунды).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.