Як мені пройти час в мілісекундах в Ruby?


98

Якщо у мене є Timeоб'єкт, отриманий від:

Time.now

а пізніше я інстантую інший об’єкт тим самим рядком, як я можу побачити, скільки мілісекунд пройшло? Другий об’єкт може бути створений тієї ж хвилини протягом наступних хвилин або навіть годин.

Відповіді:


133

Як уже було сказано, ви можете оперувати 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, і ви матимете його як ціле число, наприклад: ((закінчення - початок) * 1000.0) .to_i
Тревіс Редер

finish.to_f - start.to_f?
примхливий

1
finish - startвиходить плаваюча точка; .to_fбуло б зайвим.
ezpz

5
Якщо ви використовуєте рейли або активну підтримку, ви можете скористатися методом #in_milliseconds, щоб зробити те саме перетворення(t2 - t1).in_milliseconds
Натан Ханна

58

Ви можете додати трохи синтаксичного цукру до вищезазначеного розчину за допомогою наступного:

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трактує час як значення з плаваючою комою за секунди до десяткової точки і до наносекунд після десяткової точки (хоча nsec може бути не зовсім точним). Отже, помноживши це значення на 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:)
Гео

1
Так чи інакше,% L існує лише в Рубі 1.9;)
Рафа де Кастро

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

Приклад використання:

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

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

6

Time.now.to_f може допомогти вам, але він повертається за секунди.

Загалом, під час роботи з орієнтирами я:

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

Це дуже простий процес, тому я не впевнений, що ви справді про це питали ...


6

%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")

дасть вам поточну мітку часу в мілісекундах.


Це не говорить про те, як отримати минулий час.
Роберт

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.