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 : Blist.com 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: http://blist.com/blog/

 # 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(TimeCalc.new)
     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
       end

       hour += hour_increment
       min += min_increment

       hour.to_s + ":" + min.to_s + " " + meridiem
     end

     private

     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

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.

    Arsalan

    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: http://saaraydost.blogspot.com/

    Arsalan

    December 30, 2007 at 9:48 am

  3. I have posted the new solution with the rounding-off bug fix to my new blog: http://softwareworks.wordpress.com/

    Arsalan

    January 2, 2008 at 4:21 am


Leave a Reply