Ryan
Ryan

Reputation: 3594

Ruby (with Rails) convert a string of time into seconds?

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

Answers (6)

Gokul
Gokul

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

mark
mark

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

Max Williams
Max Williams

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

Heikki
Heikki

Reputation: 15417

'48 hours'.match(/^(\d+) (minutes|hours|days)$/) ? $1.to_i.send($2) : 'Unknown'
 => 172800 seconds

Upvotes: 4

coreyward
coreyward

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:

  • The from now is is why Chronic is needed — it handles natural language input.
  • We're specifying 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

Zabba
Zabba

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

Related Questions