Рубин: Рассчитать разницу во времени между 2 раза

Я хочу рассчитать разницу между 2 раза. start_time: 22:00 (Rails интерпретирует это как 2015-12-31 22:00:00 +0100) second_time: 02:00 (Rails интерпретирует это как 2015-12-31 02:00:00 +0100). Второй раз спустя 4 часа, так что на следующий день. Есть ли способ рассчитать эту разницу?

Я не могу просто сделать это: second_time - first_time, потому что это дает мне разницу в 22 часа вместо 4 часов.

Изменить:некоторая справочная информация: работа начинается в 22:00 и заканчивается на следующий день в 02:00. Поскольку я заполняю форму этой работы только один раз, это время для двух вышеуказанных значений: 2015-12-31 22:00:00 +0100 и 2015-12-31 02:00:00 +0100. Я не хочу, чтобы пользователь указывал время, включая дату. Реальная разница между временем должна составлять 4 часа.

Так что я на самом деле хочу вычислить разницу между 22:00 и 02:00 (на следующий день).

3 ответа

Решение

Я не понимаю, почему вы думаете, что он должен вернуться через 4 часа или почему он возвращается через 22 часа. 20 часов будет правильным для вашего примера:

require 'time'

a = Time.parse('2015-12-31 22:00:00 +0100')
b = Time.parse('2015-12-31 02:00:00 +0100')

a - b
#=> 72000.0 # difference in seconds

(a - b) / 3600
#=> 20.0  # difference in hours

Обновление: похоже, что вы имеете дело только с частью времени, а не с фактической датой. И я предполагаю, что максимальная разница, с которой вам придется иметь дело, составляет 24 часа:

def time_difference(time_a, time_b)
  difference = time_b - time_a

  if difference > 0
    difference
  else
    24 * 3600 + difference 
  end
end

a = Time.parse('2015-12-31 22:00:00 +0100')
b = Time.parse('2015-12-31 02:00:00 +0100')
time_difference(a, b) / 3600
# => 4 # hours

a = Time.parse('2015-12-31 02:00:00 +0100')
b = Time.parse('2015-12-31 22:00:00 +0100')
time_difference(a, b) / 3600
# => 20 # hours

Старый вопрос, но я сделал хороший способ справиться с этим:

def time(start,ending)
  if start != ending
    medidas=["year","month","day","hour","minute","second"]
    array=[1970,1,1,0,0,0]
    text = ""
    Time.at(ending-start).utc.to_a.take(6).reverse.each_with_index do |k,i|
      text = "#{text} #{I18n.translate medidas[i].to_sym, count: k-array[i]}"
    end
    text = text.strip.squish
    pos = text.rindex(" ",(text.rindex(" ")-1))
    unless pos.nil?
      text = text.insert(pos," and")
    end
    text = text.strip.squish #This shouldn't be needed but just in case
  else
    "0 seconds"
  end
end

Затем в config/locales/en.yml я добавил:

en:
 año:
    zero: ''
    one: '1 year'
    other: '%{count} years'
 mes:
    zero: ''
    one: '1 month'
    other: '%{count} months'
 dia:
    zero: ''
    one: '1 day'
    other: '%{count} days'
 hora:
    zero: ''
    one: '1 hour'
    other: '%{count} hours'
 minuto:
    zero: ''
    one: '1 minute'
    other: '%{count} minutes'
 segundo:
    zero: ''
    one: '1 second'
    other: '%{count} seconds'

Так, например, когда вы звоните:

start = Time.now
ending = start + (60*60)

time(start,ending)
=> "1 hour"

ending = start + (60*60*28)
time(start,ending)
=> "1 day and 4 hours"

ending = start + (53*60*5874)
time(start,ending)
=> "7 months 4 days 4 hours and 42 minutes"

Надеюсь, это полезно

Я бы написал это так (перед добавлением проверок данных), чтобы попытаться сделать это самодокументированным:

require 'time'

DT_FMT = '%Y-%m-%d %H:%M:%S %z'
SECONDS_PER_DAY = 24*60*60

def hours_elapsed(start_str, finish_str)
  start  = DateTime.strptime(start_str,  DT_FMT).to_time
  finish = DateTime.strptime(finish_str, DT_FMT).to_time
  finish = same_time_tomorrow(finish) if finish < start
  (finish-start)/3600
end

def same_time_tomorrow(time)
  time + SECONDS_PER_DAY
end

hours_elapsed '2015-12-31 22:00:00 +0100', '2015-12-31 02:00:00 +0100'
  #=>  4.0
hours_elapsed '2015-12-31 02:00:00 +0100', '2015-12-31 22:00:00 +0100'
  #=> 20.0
Другие вопросы по тегам