# Built a time calculator Project

Hello!
I finished the second certified project and I feel quite good because it took me less effort than the first one. However, I think my code could be improved, I feel like I am using ‘if’ loops all the time! It does work, but I was wondering if someone has suggestions to make it more efficient/readible and to try to find a different way of thinking about these problems. Thank you all in advance!

#### My code:

``````def add_time(start, duration, day = None):
# separate in variables start hours, minutes and AM/PM
s_time = start.split(' ')[0]
s_hours = int(s_time.split(':')[0])
s_min = int(s_time.split(':')[1])
s_period = start.split(' ')[1]

# transform into a 24:00 format
if s_period == 'PM':
s_hours += 12
d_hours = int(duration.split(':')[0])
d_min = int(duration.split(':')[1])

# calculate total minutes
extra_hours = 0
if s_min + d_min > 60:
extra_hours = (s_min + d_min) // 60
final_min = (s_min + d_min) % 60
else:
final_min = s_min + d_min
# final_min does need to have two digits
if final_min < 10:
final_min = '0' + str(final_min)

# calculate total hours and extra days
extra_days = 0
if s_hours + d_hours + extra_hours > 24:
extra_days = (s_hours + d_hours + extra_hours) // 24
final_hours = (s_hours + d_hours + extra_hours) % 24
else:
final_hours = (s_hours + d_hours + extra_hours)

# encode AM/PM for the new time
if final_hours >= 12:
final_period = 'PM'
final_hours -= 12
if final_hours == 0:
final_hours = 12
else:
final_period = 'AM'
if final_hours == 0:
final_hours = 12

# print week day
if day:
day = day.lower().capitalize()
week =[
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
'Sunday'
]

if extra_days:
if extra_days == 1:
for i in range(len(week)):
if week[i] == day:
new_day = i + 1
if new_day > 7:
new_day = new_day % 7
new_time = f"{final_hours}:{final_min} {final_period}, {week[new_day]} (next day)"
elif extra_days > 1:
for i in range(len(week)):
if week[i] == day:
new_day = i + extra_days
if new_day > 7:
new_day = new_day % 7
new_time = f"{final_hours}:{final_min} {final_period}, {week[new_day]} ({extra_days} days later)"
else:
new_time = f"{final_hours}:{final_min} {final_period}, {day}"
else:
# print relative day
if extra_days:
if extra_days == 1:
new_time = f"{final_hours}:{final_min} {final_period} (next day)"
elif extra_days > 1:
new_time = f"{final_hours}:{final_min} {final_period} ({extra_days} days later)"
else:
new_time = f"{final_hours}:{final_min} {final_period}"

return new_time
``````

Unless you have specific idea what to improve first, focus on making things simpler. Make sure to do it in small steps, checking after each one, if everything is still working.

Take a look at what happens in the last part of the code, the big `if/else` block is doing the following:

``````new_time = f"{final_hours}:{final_min} {final_period}, {week[new_day]} (next day)"
new_time = f"{final_hours}:{final_min} {final_period}, {week[new_day]} ({extra_days} days later)"
new_time = f"{final_hours}:{final_min} {final_period}, {day}"
new_time = f"{final_hours}:{final_min} {final_period} (next day)"
new_time = f"{final_hours}:{final_min} {final_period} ({extra_days} days later)"
new_time = f"{final_hours}:{final_min} {final_period}"
``````

This shows how big part is not changing, just moving the constant part outside of `if/else` will make it easier to follow.

A bit similar pattern is when `else` could be really removed, for example:

``````    if s_min + d_min > 60:
extra_hours = (s_min + d_min) // 60
final_min = (s_min + d_min) % 60
else:
final_min = s_min + d_min
``````

The `final_min` has similar parts in both cases. Extracting it before `if` would make it a kind of default case, then `if` some condition is met, something more can happen to it.

Another thing is assignments with indices, in example `start.split(' ')[0]`. Python has ability to unpack to multiple variables at the same time, for example:

``````coordinates = [0, 2]
x, y = coordinates``````
1 Like

Two suguessions to save some if/else blocks:

1. Is this simple two lines
``````    extra_hours = (s_min + d_min) // 60
final_min = (s_min + d_min) % 60
``````

doing the same thing of the following code?

``````    extra_hours = 0
if s_min + d_min > 60:
extra_hours = (s_min + d_min) // 60
final_min = (s_min + d_min) % 60
else:
final_min = s_min + d_min
``````

If the sum of `s_min` and `d_min` is less than 60, the result of `(s_min + d_min) // 60` is already 0.

1. The issue of padding zero to single digit integer to make it two digits can be done by a little trick of string formating, by adding “:02” just after the variable within curly braces of f-string, which means filling ‘0’ to make that part of the output string have a width of 2. For example:
``````>>> n = 4
>>> print(f'{n:02}')
04
>>> print(f'{n:03}')
004
``````

So it can save the the following `if` statement:

``````# final_min does need to have two digits
if final_min < 10:
final_min = '0' + str(final_min)
``````

This tricks is part of the " Format Specification Mini-Language", which have many other features. The details can be checked from Python documentation.

1 Like