Time Calculator Final Problem

Here is the code for my Time Calculator Project. The final problem involves getting the program to switch over to the next day. The iteration that triggered the last failed test is commented in the test data below.

# This function adds a duration time to a starting time and returns the result.
def add_time(start, duration, day = None):
    # Split and parse the input strings.
    [start_time, end_time] = start.split()
    [start_hour, start_minute] = [int(x) for x in start_time.split(':')]
    [duration_hour, duration_minute] = [int(x) for x in duration.split(':')]
    new_minute = start_minute + duration_minute
    duration_days = 0
    
    # Perform time calculations.
    if new_minute >= 60:
        new_hour = 1
        new_minute -= 60
    else:
        new_hour = 0
    if new_minute < 10:
        new_minute = str(new_minute).zfill(2)
    new_hour = start_hour + duration_hour + new_hour
    if duration_hour >= 24 :
        duration_days = round(new_hour / 24)
        #duration_day = f'({round(new_hour / 24)} days later)'
    elif end_time == 'PM' and (12 - start_hour) < duration_hour or (24 - start_hour) < duration_hour:
        duration_day = '(Next day)'
    if ((duration_hour % 12) + start_hour) >= 11:
        if end_time == 'AM':
            end_time = 'PM'
        else: end_time = 'AM' 
    new_hour = (new_hour % 12) or 12

    if day == None:
        if duration_days > 1:
            if end_time == 'PM':
                new_time = f'{new_hour}:{new_minute} PM ({duration_days} days later)'
            else:
                new_time = f'{new_hour}:{new_minute} AM ({duration_days} days later)'
        elif duration_days == 1:
            if end_time == 'PM':
                new_time = f'{new_hour}:{new_minute} PM (next day)'
            else:
                new_time = f'{new_hour}:{new_minute} AM (next day)'
        else:
            if end_time == 'PM':
                new_time = f'{new_hour}:{new_minute} PM'
            else:
                new_time = f'{new_hour}:{new_minute} AM'
    else:
        days = ('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday')
        day = days[(days.index(day.capitalize()) + 1 + duration_days)%7 - 1]
        if duration_days > 1:
            if end_time == 'PM':
                new_time = f'{new_hour}:{new_minute} PM, {day} ({duration_days} days later)'
            else:
                new_time = f'{new_hour}:{new_minute} AM, {day} ({duration_days} days later)'
        elif duration_days == 1:
            if end_time == 'PM':
                new_time = f'{new_hour}:{new_minute} PM, {day} (next day)'
            else:
                new_time = f'{new_hour}:{new_minute} AM, {day} (next day)'
        else:
            if end_time == 'PM':
                new_time = f'{new_hour}:{new_minute} PM, {day}'
            else:
                new_time = f'{new_hour}:{new_minute} AM, {day}'
                
    print(new_time)    
    return new_time

add_time("3:30 PM", "2:12")
add_time("11:55 AM", "3:12")
*add_time("9:15 PM", "5:30") # The failure is on this iteration here.*
add_time("11:40 AM", "0:25")
add_time("2:59 PM", "24:00")
add_time("11:59 PM", "24:05")
add_time("8:16 PM", "466:02")
add_time("5:01 AM", "0:00")
add_time("3:30 PM", "2:12", "Monday")
add_time("2:59 PM", "24:00", "Saturday")
add_time("11:59 PM", "24:05", "Wednesday")
add_time("8:16 PM", "466:02", "Tuesday")

Could it be the ‘#’ in:

#duration_day = f'({round(new_hour / 24)} days later)

Your duration_hour might be >=24 with 9:15 PM + 5:30. Your code does not do anything with the above part now because of the # and will not store anything in ‘duration day’ at these conditions.

Here is the specific failure message:
python main.py
1:08 AM
…F…

FAIL: test_next_day (test_module.UnitTests)

Traceback (most recent call last):
File “/home/runner/boilerplate-time-calculator-3/test_module.py”, line 20, in test_next_day
self.assertEqual(actual, expected, ‘Expected time to end with “(next day)” when it is the next day.’)
AssertionError: ‘2:45 AM’ != ‘2:45 AM (next day)’

  • 2:45 AM
  • 2:45 AM (next day)
    : Expected time to end with “(next day)” when it is the next day.

Ran 12 tests in 0.002s

FAILED (failures=1)

Unfortunately, the problem lies deeper:
Showing the message “(Next day)” in your code is based on duration_hour >=24 (line 19), while in reality duration_hour <24 can still mean that the new_time is on the next day (as is tested in the failed test).

The same goes for when a day is mentioned in the test: try running
add_time(“9:15 PM”, “5:30”, “Tuesday”). It should result in “6:59 PM, Wednesday (Next day)”, but your code generates “6:59 PM Tuesday”.

I think that you should find a way to either make your duration_days == 1 when PM switches to AM (which will work, but be a cumbersome exception in your code and look messy)
OR
think of another way to calculate the amount of time passed, so the Next day-message will show when the calendar would have turned a page, even when the duration_hour <24 hours (line 19)

Can you make this work within the rest (and correct!) code?

(PS: the elif on line 21 can be an ‘if’, it will look better, but does not solve the problem)

elif end_time == 'PM' and (12 - start_hour) < duration_hour or (24 - start_hour) < duration_hour:

I’ve edited your post for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (’).

‘’’
if new_hour >= 12 and new_hour < 24 and end_time == ‘PM’:
new_hour %= 12
duration_days += 1
‘’’
SUCCESS!!!

1 Like

Nic e work! Enjoy the next one (I am not until now :frowning:)

1 Like