##Updated Thoughts ##
Updated Thoughts
Final Solution
#Final Solution SinceSince a solution that reliably passes all test cases has yet to be put forth...
##Updated Thoughts ##
#Final Solution Since a solution that reliably passes all test cases has yet to be put forth...
Updated Thoughts
Final Solution
Since a solution that reliably passes all test cases has yet to be put forth...
#Final Solution Since a solution that reliably passes all test cases has yet to be put forth...
def flux_capacitor(time, mins)
#check if time in valid format
time_match = time.strip.match /^(12|11|10|0?\d):([012345]\d)\s+(AM|PM)/
#throw error on invalid time
raise(ArgumentError, "Invalid time: #{time.strip}") if not time_match
#calculate new time
strhours, strminutes, meridian = time_match.captures
hours = (meridian == "AM" ? strhours.to_i : strhours.to_i + 12)
total_minutes = hours * 60 + strminutes.to_i + mins
total_minutes = total_minutes % (24*60) # we only want the minutes that fit within a day
adjusted_hours, adjusted_minutes = total_minutes.divmod(60)
if adjusted_hours > 12
adjusted_hours -= 12
meridian = "PM"
else
meridian = "AM"
end
"%d:%02d %s" % [adjusted_hours, adjusted_minutes, meridian]
end
Testing:
[ "11:13 PM",
"13:09 PM", #invalid!
"1:59 AM",
"04:49 PM",
"4:79 PM" #invalid!
].each do |time|
begin
puts flux_capacitor(time, 0)
rescue
puts $!
end
end
puts "----------"
puts "#{flux_capacitor("11:13 PM", 10)}, expected: 11:23 PM"
puts "#{flux_capacitor("11:13 PM", 12*60)}, expected 11:13 AM"
puts "#{flux_capacitor("11:13 PM", 24*60)}, expected 11:13 PM"
puts "#{flux_capacitor("11:13 PM", 24*60 + 1)}, expected 11:14 PM"
puts "#{flux_capacitor("11:59 AM", 62)}, expected 1:01 PM"
puts "#{flux_capacitor("11:59 PM", 62)}, expected 1:01 AM"
#Final Solution Since a solution that reliably passes all test cases has yet to be put forth...
def flux_capacitor(time, mins)
#check if time in valid format
time_match = time.strip.match /^(12|11|10|0?\d):([012345]\d)\s+(AM|PM)/
#throw error on invalid time
raise(ArgumentError, "Invalid time: #{time.strip}") if not time_match
#calculate new time
strhours, strminutes, meridian = time_match.captures
hours = (meridian == "AM" ? strhours.to_i : strhours.to_i + 12)
total_minutes = hours * 60 + strminutes.to_i + mins
total_minutes = total_minutes % (24*60) # we only want the minutes that fit within a day
adjusted_hours, adjusted_minutes = total_minutes.divmod(60)
if adjusted_hours > 12
adjusted_hours -= 12
meridian = "PM"
else
meridian = "AM"
end
"%d:%02d %s" % [adjusted_hours, adjusted_minutes, meridian]
end
Testing:
[ "11:13 PM",
"13:09 PM", #invalid!
"1:59 AM",
"04:49 PM",
"4:79 PM" #invalid!
].each do |time|
begin
puts flux_capacitor(time, 0)
rescue
puts $!
end
end
puts "----------"
puts "#{flux_capacitor("11:13 PM", 10)}, expected: 11:23 PM"
puts "#{flux_capacitor("11:13 PM", 12*60)}, expected 11:13 AM"
puts "#{flux_capacitor("11:13 PM", 24*60)}, expected 11:13 PM"
puts "#{flux_capacitor("11:13 PM", 24*60 + 1)}, expected 11:14 PM"
puts "#{flux_capacitor("11:59 AM", 62)}, expected 1:01 PM"
puts "#{flux_capacitor("11:59 PM", 62)}, expected 1:01 AM"
More testing is required:
flux_capacitor("11:59 AM", 62)
=> "12:21 AM"
Definitely test some corner cases.
##Updated Thoughts ##
I think you should completely rethink the way you are handling time.
Use a regex to validate that time is a valid string, then simply use string.split
to get each portion of the time: hours, minutes, and AM/PM.
Next you should convert those into a quantity of minutes:
hours += 12 if meridian == 'PM'
total_minutes = hours*60+minutes+mins
Next I would recalculate the time as a 24-hour time (which goes up to 23 hours, 59 minutes):
# this is integer math so the decimal portion will be discarded
# adjusted_minutes may be greater than 23, but adjusted_minutes should always be less than 60
adjusted_hours = (total_minutes / 60)
adjusted_minutes = total_minutes - (60*adjusted_hours)
# modulus 24 converts adjusted_hours into 24-hour time
adjusted_hours = adjusted_hours % 24
Now convert to 12 hour time if necessary and determine if this is AM or PM
# the added mins may have been several days worth, so adjusted_hours might be very large.
if adjusted_hours > 12
meridian = "PM"
adjusted_hours -= 12
else
meridian = "AM"
end
Finally return a string of the new time:
# zero pad the minutes, as this is expected for a time
return "%d:%02d %s" % [adjusted_hours, adjusted_minutes, meridian]
More testing is required:
flux_capacitor("11:59 AM", 62)
=> "12:21 AM"
Definitely test some corner cases.
More testing is required:
flux_capacitor("11:59 AM", 62)
=> "12:21 AM"
Definitely test some corner cases.
##Updated Thoughts ##
I think you should completely rethink the way you are handling time.
Use a regex to validate that time is a valid string, then simply use string.split
to get each portion of the time: hours, minutes, and AM/PM.
Next you should convert those into a quantity of minutes:
hours += 12 if meridian == 'PM'
total_minutes = hours*60+minutes+mins
Next I would recalculate the time as a 24-hour time (which goes up to 23 hours, 59 minutes):
# this is integer math so the decimal portion will be discarded
# adjusted_minutes may be greater than 23, but adjusted_minutes should always be less than 60
adjusted_hours = (total_minutes / 60)
adjusted_minutes = total_minutes - (60*adjusted_hours)
# modulus 24 converts adjusted_hours into 24-hour time
adjusted_hours = adjusted_hours % 24
Now convert to 12 hour time if necessary and determine if this is AM or PM
# the added mins may have been several days worth, so adjusted_hours might be very large.
if adjusted_hours > 12
meridian = "PM"
adjusted_hours -= 12
else
meridian = "AM"
end
Finally return a string of the new time:
# zero pad the minutes, as this is expected for a time
return "%d:%02d %s" % [adjusted_hours, adjusted_minutes, meridian]