Time Calculator Project: Cyclomatic Complexity Too High

Hey guys. I just came from javascript and im learning python as i build this project. I know my code is bulkier than probably needs to be but i think im on the right track to get this to work. However im getting the cyclomatic complexity error saying theres 16 and 15 is the threshold. Im assuming that means i have 16 if/else statements and the error triggers at 15 or more. From what ive googled i dont think the error is a real error but more of a warning.
My code also only half works. It does the adding of the time and tracking of the AM or PM correctly. It doesnt track the day of the week or number of days added. At least if it does do that its not making it through my final print if else statements.
Heres the project: https://www.freecodecamp.org/learn/scientific-computing-with-python/scientific-computing-with-python-projects/time-calculator

Heres the code:

def add_time(start, duration, day=None):
  #Setting up initial variables and splitting the arguments into usable parts.
  carry_the_one = 0
  new_time = [0, 0]
  duration_split = duration.split(":")
  start_split = start.split(":")
  days_added = 0
  
  #This part checks if there is am or pm but i realized the challenge requires am or
  #pm in the starting argument so the if statement is unnecessary.
  #But it works so im keeping it for now.
  j = None #j keeps track of if am or pm
  if "AM" or "PM" in start_split[1]:
    x = start_split[1].split(" ")
    start_split[1] = x[0]
    j = x[1] 
  
  #adds the time together and creates a multiplier variable as well as a days_added variable
  new_time[1] = int(duration_split[1]) + int(start_split[1])
  if new_time[1] > 59:
    carry_the_one = 1
    new_time[1] -= 60
  new_time[0] = int(start_split[0]) + int(duration_split[0]) + carry_the_one
  multiplier = int(new_time[0] / 12)

  #determines how many days were added and stores in a variable
  if j == "PM" and multiplier == 1:
    days_added = "(next day)"
  elif j =="AM" and multiplier == 2:
    days_added = "(next day)"
  elif j == "PM" and multiplier > 2 and multiplier % 2 == 1:
    days_added = multiplier / 2 + 1
  else:
    days_added = multiplier / 2

  #checks if there was a starting day specified and then determins the weekday after the time was added.
  if day != None:
    day = day.capitalize()
    day_of_week = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
    day_index = day_of_week.index(day)
    day_index += days_added
    if day_index > 6:
      day_multi = int(day_index / 7)
      day_index -= 7 * day_multi

  #Determines if am or pm. Can probably use days_added to make the code cleaner. Might change later.
  if new_time[0] > 12:
    new_time[0] -= 12 * multiplier 
    if multiplier % 2 == 1 and j == "AM":
      j = "PM"
    elif multiplier % 2 == 1 and j == "PM":
      j = "AM" 
  
  #This chain of if statements seems redundant somehow. 
  if day != None and days_added > 1:
    print(str(new_time[0]) + ":" + str(new_time[1]) + " " + j + ", " + day_of_week[day_index] + "(" + str(days_added) + " days later)")
  elif day != None and days_added == 1:
    print(str(new_time[0]) + ":" + str(new_time[1]) + " " + j + ", " + day_of_week[day_index] + days_added)
  elif day != None and days_added == 0:
    print(str(new_time[0]) + ":" + str(new_time[1]) + " " + j + ", " + day_of_week[day_index])
  elif day == None and days_added > 1:
    print(str(new_time[0]) + ":" + str(new_time[1]) + " " + j + "(" + days_added + " days later)")
  elif day == None and days_added == 1:
    print(str(new_time[0]) + ":" + str(new_time[1]) + " " + j + days_added)
  else:
    print(str(new_time[0]) + ":" + str(new_time[1]) + " " + j)

On the chain of if statements:

More generally, I would recommend converting the start time to 24 hour time for easier calculations instead of trying to track AM and PM. Some tools that might help:

  • // (floor division)
  • % (modulo operator)
  • divmod() (both in one function)

"AM" or "PM" in start_split[1] evaluates as ("AM") or ("PM" in start_split[1]), which is probably not what you want and is always truthy.

1 Like

Thank you for the feedback! Im definitely going to implement a lot of your suggestions. I got my original excessive code almost to pass. The only thing tripping me up now is that my math works out so that any time 12 should show up in the hours position its zero instead. I might be able to fix that with the 24 hour suggestion. The other one is if there is a single digit in the minutes position (i.e. 1:00-1:09) its drops the leading 0 (eg 1:0-1:9). Any advice on resolving those issues?

For zero padding, you can either use the str.zfill(n) method, which will return a new padded string of width n, or format inside a f-string. For example, f"{9:02}:00" will return 09:00. More on formatting here (f-strings and str.format() share syntax for formatting).

1 Like