Как мне написать функцию для преобразования длительности во время в миллисекундах и учета недопустимых значений?

Я использую Rails 5 с Ruby 2.4. Я хочу преобразовать строку, которая представляет продолжительность (время) в миллисекунды, поэтому у меня есть эта функция

  def duration_in_milliseconds(input)
    if input && input.count("a-zA-Z ") == 0 
      if input.index(".") && !input.index(":")
        input.gsub!(/\./, ':')
      end
      # replace bizarre apostraphes where they intended ":"'s
      input.gsub!(/'/, ':')  
      # Strip out unnecessary white space 
      input.gsub!(/\A\p{Space}+|\p{Space}+\z/, '')  
      input.split(':').map(&:to_f).inject(0) { |a, b| a * 60 + b } * 1000
    else
      0
    end
  end

Это отлично подходит для таких строк, как «6:52» (6 минут, 52 секунды), но также работает и для таких строк, как «52: 6» (что неверно, «52:06» будет правильным). Я хочу, чтобы функция возвращала ноль, если кто-то вводит одну цифру в любом месте, кроме первого числа перед «:». Как мне это сделать? Заметьте, что я все еще хочу, чтобы длительность вроде «15: 24,8» выполнялась в обычном режиме (то есть 15 минут, 24 секунды и восемь десятых секунды).


person Dave    schedule 29.01.2017    source источник
comment
Требуется ли место для минут или 5.678 допустимый ввод?   -  person Jordan Running    schedule 29.01.2017
comment
Привет, да, 5.678 действительно. Хорошая точка зрения.   -  person Dave    schedule 30.01.2017
comment
Ваш текущий код позволяет использовать . в качестве разделителя вместо :. В таком случае это 1.23 одна минута 23 секунды или 1,23 секунды?   -  person Jordan Running    schedule 30.01.2017


Ответы (1)


Я пытался найти решение этой проблемы, но в итоге пришлось переработать код.

Я начал разбивать строку и удалять все пробелы. Чтобы сначала удалить пробелы, я проверяю, что нет начальных и конечных пробелов, а затем добавляю любое количество дополнительных пробелов до или после символов :.

Затем я присваиваю значения, полученные из разделения, трем переменным, которые я назвал hr, min и seg. Если вы не знакомы с этим, переменные заполняются слева направо, и, если элементов недостаточно, оставшиеся переменные получают nil.

Затем условие. Для этого я говорю: «Верните ноль, если min или seg не совпадают с двумя последовательными числовыми символами, пока они присутствуют».

И, наконец, я суммирую их соответствующие значения в секундах, что возвращает количество секунд. И в конце строки я конвертирую его в миллисекунды, умножая его на 1000

def duration_in_milliseconds(input)
  hr, min, seg = input.strip.split(/\s*:\s*/)
  return 0 if [min, seg].any? {|value| value && !(value =~ /\d\d/)}
  (hr.to_i * 60 * 60 + min.to_i * 60 +  seg.to_i) * 1000
end

И я попробовал это на нескольких строках, чтобы убедиться, что это работает.

duration_in_milliseconds("0:00:01")             # => 1000
duration_in_milliseconds("0:01:01")             # => 61000
duration_in_milliseconds("1:01:01")             # => 3661000
duration_in_milliseconds("0:15")                # => 900000
duration_in_milliseconds("1:   05")             # => 3900000
duration_in_milliseconds("1:5")                 # => 0
duration_in_milliseconds("1:5 ")                # => 0
duration_in_milliseconds(" \t 1 : 05  : 15   ") # => 3915000
duration_in_milliseconds("1:5:15")              # => 0
duration_in_milliseconds("1")                   # => 3600000
duration_in_milliseconds("1:5D:15")             # => 0

Я надеюсь, что это помогло и ответило на вопрос (в некотором роде), если нет, пожалуйста, не стесняйтесь пинговать меня.

Ваше здоровье

Fede

person fiachetti    schedule 29.01.2017