Shpigford
Shpigford

Reputation: 25378

Ruby: Convert time to seconds?

How can I convert a time like 10:30 to seconds? Is there some sort of built in Ruby function to handle that?

Basically trying to figure out the number of seconds from midnight (00:00) to a specific time in the day (such as 10:30, or 18:45).

Upvotes: 23

Views: 42548

Answers (8)

Daniel Vandersluis
Daniel Vandersluis

Reputation: 94304

You can use DateTime#parse to turn a string into a DateTime object, and then multiply the hour by 3600 and the minute by 60 to get the number of seconds:

require 'date'

# DateTime.parse throws ArgumentError if it can't parse the string
if dt = DateTime.parse("10:30") rescue false 
  seconds = dt.hour * 3600 + dt.min * 60 #=> 37800
end

As Josh Lee pointed out in the comments, you could also use Time#seconds_since_midnight if you have ActiveSupport:

require 'active_support'
Time.parse("10:30").seconds_since_midnight #=> 37800.0

Upvotes: 37

iBug
iBug

Reputation: 37317

I like these answers very much, especially Teddy's for its tidyness.

There's one thing to note. Teddy's answer gives second of day in current region and I haven't been able to convert Date.today.to_time to UTC. I ended up with this workaround:

Time.now.to_i % 86400

It's based on the fact that Time.now.to_i gives seconds since Unix Epoch which is always 1970-01-01T00:00:00Z, regardless of your current time zone. And the fact that there's 86400 seconds in a day as well. So this solution will always give you seconds since last UTC midnight.

Upvotes: 3

Vadym Tyemirov
Vadym Tyemirov

Reputation: 8853

In plain ruby the fastest is the sum of time parts:

require 'benchmark'
require 'time'

Benchmark.bm do |x|
  x.report('date') { 100_000.times { Time.now.to_i - Date.today.to_time.to_i } }
  x.report('parse') { 100_000.times { Time.now.to_i - Time.parse('00:00').to_i } }
  x.report('sum') { 100_000.times { Time.now.hour * 3600 + Time.now.min * 60 + Time.now.sec } }
end

       user     system      total        real
date  0.820000   0.000000   0.820000 (  0.822578)
parse  1.510000   0.000000   1.510000 (  1.516117)
sum  0.270000   0.000000   0.270000 (  0.268540)

So, here is a method that takes timezone into account, if needed

def seconds_since_midnight(time: Time.now, utc: true)
  time = time.utc if utc
  time.hour * 3600 + time.min * 60 + time.sec
end

Upvotes: 0

Anoop
Anoop

Reputation: 1435

You can simply use

Time.parse("10:30").seconds_since_midnight

Upvotes: 3

Teddy
Teddy

Reputation: 18572

Yet another implementation:

Time.now.to_i - Date.today.to_time.to_i # seconds since midnight

Upvotes: 15

Gregology
Gregology

Reputation: 1735

require 'time'

def seconds_since_midnight(time)
  Time.parse(time).hour * 3600 + Time.parse(time).min * 60 + Time.parse(time).sec
end

puts seconds_since_midnight("18:46")

All great answers, this is what I ended up using.

Upvotes: 1

Derek
Derek

Reputation: 326

The built in time library extends the Time class to parse strings, so you could use that. They're ultimately represented as seconds since the UNIX epoch, so converting to integers and subtracting should get you what you want.

require 'time'
m = Time.parse('00:00')
t = Time.parse('10:30')

(t.to_i - m.to_i)
=> 37800

There's also some sugar in ActiveSupport to handle these types of things.

Upvotes: 9

bnaul
bnaul

Reputation: 17656

Perhaps there is a more succinct way, but:

t = Time.parse("18:35")
s = t.hour * 60 * 60 + t.min * 60 + t.sec

would do the trick.

Upvotes: 3

Related Questions