简体   繁体   中英

Getting “argument out of range” when trying to turn a duration into milliseconds in Rails 4

I'm using Rails 4.2.4. I have the below method for converting a time (duration) to milliseconds …

Time.parse(convert_to_hrs(duration)).seconds_since_midnight * 1000

in which the method “convert_to_hrs” is defined as

    def convert_to_hrs(string)
      case string.count(':')
      when 0
        '00:00:' + string.rjust(2, '0')
      when 1
        '00:' + string
      else
        string
      end
    end

However, if the duration is something really big (eg “34:13:00” -- read: 34 hours, 13 minutes, and zero seconds), the above fails with the error

Error during processing: argument out of range
/Users/mikea/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/time.rb:302:in `local'
/Users/mikea/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/time.rb:302:in `make_time'
/Users/mikea/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/time.rb:366:in `parse'
/Users/mikea/Documents/workspace/myproject/app/services/my_service.rb:25:in `block in process_page_data'
/Users/mikea/Documents/workspace/myproject/app/services/my_service.rb:22:in `each'
/Users/mikea/Documents/workspace/myproject/app/services/my_service.rb:22:in `process_page_data'

How do I rewrite my first line to accurately convert duration into milliseconds?

Time.parse is throwing error, becuase values you passing in duration variable is out of range.

For Ex: Time.parse(convert_to_hrs('59:59')) as per your written code , it's return 2016-07-27 00:59:59 +0530

Here the value 59:59 consider as minutes:seconds , so if you pass the value 60:60 then it will raise the error argument out of range

Here is the official documentation for parse method of Time

Hope this will help you.

If you know you're always going to be using a hours:minutes:seconds format, but the number in each field isn't guaranteed to be inside the 'normal' range (eg 0-23 for hours, 0-59 for minutes, etc), then you're probably best off doing it 'manually' using something like this:

def duration_in_milliseconds(input)
  h, m, s = input.split(':').map(&:to_i)
  (h.hours + m.minutes + s.seconds) * 1000
end

puts duration_in_milliseconds('34:13:00') #=> 123180000

Note that this only works with ActiveSupport, but you have that, since you've specified Rails. Also, this assumes you're always getting all three terms (eg 5 seconds is 00:00:05). The full setup that accepts shorter strings as well would want to also use your convert_to_hrs method.

Note also that this works even if formatting isn't strictly 'time-like', as long as you have consistent colons as seperators:

puts duration_in_milliseconds('1:1:5') #=> 3665000

The Numeric#hours , Numeric#minutes and Numeric#seconds methods are provided by ActiveSupport, as part of active_support/core-ext/time.rb . They aren't particularly documented, but they return ActiveSupport::Duration objects, which have fancy methods for interacting with Time and Date issues like 5.days.ago , but when treated as an integer are effectively a number of seconds.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM