user9769384
user9769384

Reputation: 60

How to add hours and minutes that are stored as strings

I'm trying to add hours and minutes that are stored in the database like this:

+----+---------+-------+
| id | user_id | time  |
+----+---------+-------+
|  1 |       4 | 03:15 |
|  2 |       4 | 02:22 |
+----+---------+-------+

The time field is a string. How can I add the hours and minutes expressed by the strings like 05:37?

I tried this

current_user.table.pluck(:time).sum(&:to_f)

but the output is only 5.

Upvotes: 3

Views: 2439

Answers (2)

Nezir
Nezir

Reputation: 6925

Please check this sample of summing time in ruby:

require 'time'

t = Time.parse("3:15")
puts t.strftime("%H:%M")

t2 = Time.parse("02:22")
puts t2.strftime("%H:%M")
t3 = t.to_i + t2.to_i

puts Time.at(t3).utc.strftime("%H:%M")

This is fast sum of times below 24 hour span. For correct solution for every case please check @Cary code above.

Here is a small Ruby Gem made from @Cary code sample which extends Ruby Array class with method sum_strings in example like:

["12:23","23:30","1:2"].sum_strings(':') will result as "36:55"

Gem https://github.com/nezirz/sum_strings/

Sample project with using Gem: https://github.com/nezirz/use_sum_strings

Upvotes: 6

Cary Swoveland
Cary Swoveland

Reputation: 110725

If you read the times from your table into an array you obtain something like

arr = ["03:15", "02:22"]

You could then write

arr.sum do |s|
  h, m = s.split(':').map(&:to_i)
  60*h + m
end.divmod(60).join(':')
  #=> "5:37"

See Array#sum (introduced in MRI v2.4) and Integer#divmod. To support Ruby versions earlier than 2.4 use Enumerable#reduce in place of Array#sum.

The three steps are as follows.

mins = arr.sum do |s|
  h, m = s.split(':').map(&:to_i)
  60*h + m
end
  #=> 337
hm = mins.divmod(60)
  #=> [5, 37]
hm.join(':')
  #=> "5:37"

Upvotes: 10

Related Questions