Reputation: 3594
So, I've got a string of time... something along the lines of
'4 hours'
'48 hours'
'3 days'
'15 minutes'
I would like to convert those all into seconds. For '4 hours'
, this works fine
Time.parse('4 hours').to_i - Time.parse('0 hours').to_i
=> 14400 # 4 hours in seconds, yay
However, this doesn't work for 48 hours (outside of range error). It also does not work for 3 days (no information error), etc.
Is there a simple way to convert these strings into seconds?
Upvotes: 3
Views: 8680
Reputation: 2336
Chronic will work, but Chronic Duration is a better fit. It can parse a string and give you seconds.
require "chronic_duration"
ChronicDuration::parse('15 minutes')
# or
ChronicDuration::parse('4 hours')
http://everydayrails.com/2010/08/11/ruby-date-time-parsing-chronic.html
Upvotes: 2
Reputation: 10574
4.hours => 14400 seconds
4.hours.to_i 14400
4.hours - 0.hours => 14400 seconds
def string_to_seconds string
string.split(' ')[0].to_i.send(string.split(' ')[1]).to_i
end
This helper method will only work if the time is in the format of number[space]hour(s)/minute(s)/second(s)
Upvotes: 4
Reputation: 32955
>> strings = ['4 hours', '48 hours', '3 days', '15 minutes', '2 months', '5 years', '2 decades']
=> ["4 hours", "48 hours", "3 days", "15 minutes", "2 months", "5 years", "2 decades"]
>> ints = strings.collect{|s| eval "#{s.gsub(/\s+/,".")}.to_i" rescue "Error"}
=> [14400, 172800, 259200, 900, 5184000, 157788000, "Error"]
Upvotes: -1
Reputation: 15417
'48 hours'.match(/^(\d+) (minutes|hours|days)$/) ? $1.to_i.send($2) : 'Unknown'
=> 172800 seconds
Upvotes: 4
Reputation: 80140
What you're asking Ruby to do with Time.parse is determine a time of day. That's not what you are wanting. All of the libraries I can think of are similar in this aspect: they are interested in absolute times, not lengths of time.
To convert your strings into time formats that we can work with, I recommend using Chronic (gem install chronic
). To convert to seconds, we can do everything relative to the current time, then subtract that time to get the absolute number of seconds, as desired.
def seconds_in(time)
now = Time.now
Chronic.parse("#{time} from now", :now => now) - now
end
seconds_in '48 hours' # => 172,800.0
seconds_in '15 minutes' # => 900.0
seconds_in 'a lifetime' # NoMethodError, not 42 ;)
A couple quick notes:
from now
is is why Chronic is needed — it handles natural language input.now
to be safe from a case where Time.now changes from the time that Chronic does it's magic and the time we subtract it from the result. It might not occur ever, but better safe than sorry here I think.Upvotes: 6
Reputation: 65517
I'm sure you would get some good work out of chronic gem.
Also, here is some good to know info about dates/times in ruby
Upvotes: 1