Saari Development

Ali Rizvi's Technical Blog as a Professional Software Development Engineer

Ruby : Time Math Interview Problem Done Test First

with 3 comments

Question from : Career Page

# Without using any built in date or time functions, write a function or method
# that accepts two mandatory arguments. The first argument is a string of the
# format “[H]H:MM {AM|PM}” and the second argument is an integer. Assume the
# integer is the number of minutes to add to the string. The return value of
# the function should be a string of the same format as the first argument.
# For example AddMinutes(“9:13 AM”, 10) would return “9:23 AM”. The exercise
# isn’t meant to be too hard. I just want to see how you code. Feel free to
# do it procedurally or in an object oriented way, whichever you prefer. Use
# any language you want. Write production quality code.
# Question Source:

# the following solution was developed using TDD

require ‘test/unit’

class TestTimeCalc < Test::Unit::TestCase def setup @time = "9:13 AM" end def test_new_time_cal assert_not_nil( end def test_add_minute_zero assert_equal(@time, TimeCalc.add_minutes(@time, 0)) end def test_add_minute_ten assert_equal("9:23 AM", TimeCalc.add_minutes(@time, 10)) end def test_add_minute_thirteen assert_equal("9:26 AM", TimeCalc.add_minutes(@time, 13)) end def test_add_hour assert_equal("10:13 AM", TimeCalc.add_minutes(@time, 60)) end def test_add_two_hours_fifteen_minutes assert_equal("11:28 AM", TimeCalc.add_minutes(@time, 135)) end def test_add_past_meridiem # 785 minutes = 13 hours and 5 minutes assert_equal("10:18 PM", TimeCalc.add_minutes(@time, 785)) end def test_alpha_hour_min_format_throws_exception assert_raise(ArgumentError) { TimeCalc.add_minutes("AB:CD AM", 10) } end def test_bad_meridiem_throws_exception assert_raise(ArgumentError) { TimeCalc.add_minutes("AB:CD TM", 10) } end def test_hr_greater_than_twelve assert_raise(ArgumentError) { TimeCalc.add_minutes("13:00 PM", 10) } end def test_min_greater_than_fifty_nine assert_raise(ArgumentError) { TimeCalc.add_minutes("12:60 PM", 10) } end end # end class TestTimeCalc class TimeCalc def self.add_minutes(time, minutes) (hour, min, meridiem) = parse_time_string(time) hour_increment = (min + minutes)/60 min_increment = (min + minutes)%60 - min if (hour_increment >= 12)
meridiem = (meridiem == ‘AM’ ? ‘PM’ : ‘AM’)
hour_increment -= 12

hour += hour_increment
min += min_increment

hour.to_s + “:” + min.to_s + ” ” + meridiem


def self.parse_time_string(time)
raise ArgumentError unless (matches = time.match(/(\d{1,2}):(\d{1,2})\s+(\w{2})/))
matches = time.match(/^(\d{1,2}):(\d{1,2})\s+([A|P]M)$/)
hour = matches[1].to_i
min = matches[2].to_i
meridiem = matches[3]
raise ArgumentError unless (hour <= 12) raise ArgumentError unless (min < 60) return [hour, min, meridiem] end end # end class TimeCalc [/sourcecode]


Written by imsaar

December 28, 2007 at 11:18 pm

Posted in code, ruby

3 Responses

Subscribe to comments with RSS.

  1. Nice work. Unfortunately, I am not as mathematically inclined as you are. My solution would have been far less impressive but I will try to code it and post it here, if possible.


    December 29, 2007 at 3:53 am

  2. Couldn’t figure how to post serious html on the blog (to post source code)! After hacking a large part of the night, I have the code tested and ready. Here it is:


    December 30, 2007 at 9:48 am

  3. I have posted the new solution with the rounding-off bug fix to my new blog:


    January 2, 2008 at 4:21 am

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: