snippetrubyModerate
Convert total minutes into "Hours:minute:seconds" for marathon data
Viewed 0 times
totalmarathonconvertintohourssecondsforminutesdataminute
Problem
The point of the script below is to read in the 10th column which is the total number of minutes a runner took to finish the marathon and convert it into form of "hours:minutes:seconds". Is there a better way?
Time starts as in total minutes in decimal format:
Example Data:
require 'csv'
File.open('bostonmarathon-2012-results.txt', 'w') { |f|
skip = true
CSV.foreach("bostonmarathon-2012-results.csv") do |row|
if skip
skip = false
else
total_seconds = row[10].to_f * 60
seconds = total_seconds % 60
minutes = (total_seconds / 60) % 60
hours = total_seconds / (60 * 60)
f.puts(format("%02d:%02d:%02d", hours, minutes, seconds))
end
end
}Time starts as in total minutes in decimal format:
142.93Example Data:
division,name,city,gender,age,official,bib,overall,state,genderdiv,net,country
4 / 26,"Soejima, Masazumi",Fukuoka City,M,41,83.45,W1,4 / 35,,4 / 26,83.45,JPN
14 / 4335,"Gebremariam, Gebregziabher",Tigray,M,27,142.93,2,14 / 21616,,14 / 12621,142.93,ETH
6 / 26,"Van Dyk, Ernst F.",Paarl,M,39,84.38,W2,6 / 35,,6 / 26,84.38,RSA
2 / 26,"Fearnley, Kurt H.",Hamilton,M,31,81.65,W3,2 / 35,,2 / 26,81.65,AUS
3 / 26,"Hokinoue, Kota",Iizuka,M,38,83.43,W4,3 / 35,,3 / 26,83.43,JPN
Solution
-
Use
-
For the time-formatting you can use
Pretty clean, I think.
Alternatively, here's a hacky(!) idea. You could just treat the seconds as a regular unix timestamp, and do something like
The assumption here is of course that no one took more than 24 hours to complete the marathon. If they did, the hour would of course roll over. It seems like an ok assumption in this particular case, but it's obviously not something that'd work for any context. It's kinda clever, but it's definitely a hack.
Use
do...end for multiline blocks. You're already doing it for the innermost block, but not the File.open block for some reason-
CSV.foreach accepts a hash of options. One of them is :headers which you can set to true or :first_row. This will- skip the header row when iterating (so you can skip
skipand theif..else-branching), and
- let you refer to a column by its header text instead of an opaque numerical index.
For the time-formatting you can use
#divmod to get both quotient and remainder of a division in one go. Add some array destructuring, and you get this:hours, remainder = total_seconds.divmod(60**2)
minutes, seconds = remainder.divmod(60)Pretty clean, I think.
Alternatively, here's a hacky(!) idea. You could just treat the seconds as a regular unix timestamp, and do something like
Time.at(total_seconds).strftime("%k:%M:%S")The assumption here is of course that no one took more than 24 hours to complete the marathon. If they did, the hour would of course roll over. It seems like an ok assumption in this particular case, but it's obviously not something that'd work for any context. It's kinda clever, but it's definitely a hack.
Code Snippets
hours, remainder = total_seconds.divmod(60**2)
minutes, seconds = remainder.divmod(60)Time.at(total_seconds).strftime("%k:%M:%S")Context
StackExchange Code Review Q#55948, answer score: 11
Revisions (0)
No revisions yet.