2013-04-12 6 views
1

У меня есть Float, который представляет секунды. Итак, у меня может быть 38,93 секунды. Я ищу «рубиновый» способ получить часы, если это возможно, или минуты, если часы не возможны, и если минуты и часы не возможны только секунды. Когда я говорю, я могу сказать:Преобразование секунд (поплавков) в часы/секунды/минуты

Если времени меньше 3600 секунд, это будет минуты или секунды. Если будет меньше 60 секунд, это будут секунды.

Сейчас я делаю несколько, если посмотреть, что это должно быть, но я думаю, что, возможно, должен быть более чистый способ.

if input > 3600 
    return input/3600, 'hours' 
elseif input < 3600 && input > 60 
    return input/60, 'minutes' 
else 
    return input, 'seconds' 

Благодаря

+0

38.93 не является Fixnum. –

+0

Дэвид, извините, я имею в виду Float –

ответ

-1
input = 4000 #input in seconds 
h = {(60..3599) => ["input/60",'Minutes'], (0..59) => ["input",'Seconds'],(3600..Float::INFINITY) => ["input/3600",'Hours']} 
h.each_pair {|k,v| p "#{v.last} is #{eval(v.first)}" if k.include? input} 

input = 1100 #input in seconds 
h = {(60..3599) => ["input/60",'Minutes'], (0..59) => ["input",'Seconds'],(3600..Float::INFINITY) => ["input/3600",'Hours']} 
h.each_pair {|k,v| p "#{v.last} is #{eval(v.first)}" if k.include? input} 

input = 14 #input in seconds 
h = {(60..3599) => ["input/60",'Minutes'], (0..59) => ["input",'Seconds'],(3600..Float::INFINITY) => ["input/3600",'Hours']} 
h.each_pair {|k,v| p "#{v.last} is #{eval(v.first)}" if k.include? input} 

Выход:

"Hours is 1" 
"Minutes is 18" 
"Seconds is 14" 
+0

Это выглядит хорошо, но я просто хочу вернуть «часы» или «минуты» или «секунды», а не три из них. –

+0

@HommerSmith. Я обновил свой код. Надеюсь, вам понравится. –

5

ИМХО сазе с диапазонами будет немного чище:

def some_method_name(input) 
    case input 
    when 0...60 
    input, 'seconds' 
    when 60...3600 
    input/60, 'minutes' 
    else 
    input/3600, 'hours' 
    end 
end 

Другой соответствую ACH будет извлекать часы, минуты и секунды первая:

def some_method_name(input) 
    hours, seconds = input.divmod(3600) 
    minutes, seconds = seconds.divmod(60) 

    if hours > 0 
    hours, 'hours' 
    elsif minutes > 0 
    minutes, 'minutes' 
    else 
    seconds, 'seconds' 
    end 
end 

В Rails вы бы, конечно, использовать встроенные pluralization.

1

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

TimeInt = Struct.new :name, :secs 
INTERVALS = [ TimeInt[:days, 60*60*24], TimeInt[:hours, 60*60], 
       TimeInt[:minutes, 60], TimeInt[:seconds, 1] ] 

def time_with_adaptive_units(secs) 
    ti = INTERVALS.find { |ti| secs >= ti.secs } || INTERVALS.last 
    val, name = (secs.to_f/ti.secs).round, ti.name.to_s 
    name.sub!(/s$/,'') if val == 1 
    "#{val} #{name}" 
end 

[5] pry(main)> time_with_adaptive_units(1) 
=> "1 second" 
[6] pry(main)> time_with_adaptive_units(45) 
=> "45 seconds" 
[7] pry(main)> time_with_adaptive_units(450) 
=> "7 minutes" 
[8] pry(main)> time_with_adaptive_units(4500) 
=> "1 hour" 
[9] pry(main)> time_with_adaptive_units(45000) 
=> "12 hours" 
[10] pry(main)> time_with_adaptive_units(450000) 
=> "5 days" 
+0

Это хорошо! Где я должен определить Struct? Используя Rails, я хотел поместить этот метод в ApplicationHelper. Если я определяю структуру внутри самого метода, я получаю ошибку «динамическое постоянное присваивание». –

+0

@HommerSmith Я бы определил Struct и INTERVALS прямо над определением метода, если это единственное место, которое вы будете использовать. Это просто маленький компаньон, чтобы сделать собственную маркировку данных INTERVALS. – dbenhur

+0

как мой? :) –

0

Там, что я мог думать:

total_seconds = 23456 
intervals = [3600, 60, 1].inject({rem: total_seconds, parts:[]}) do |memo, factor| 
    count = (memo[:rem]/factor).floor 
    memo[:rem] = memo[:rem] - (count * factor) 
    memo[:parts] << count 
    memo 
end 

И вы могли бы закончить его с

itervals[:parts].zip(['hours', 'minutes', 'seconds']).map{|p| p.join(' ')}.join(', ') 

Вы также можете видеть, что это тривиально, чтобы расширить это несколько дней, недель, месяцев, лет, десятилетий и столетий, если вы хотите: D

Смежные вопросы