Reputation: 60
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
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
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