As part of Udacity’s Intro to Computer Science online course that I’m taking, I ran into this interesting exercise. The goal was to create a function that takes two dates as input and counts the days between them. The first date is always earlier than the second. My solution was probably not the most elegant and my code could be shorter and more efficient. The logic however was the important thing to understand, and that is also what I want to focus on in this article. This exercise was written in Python.
If we put the two input dates on a timeline, the algorithm is working from the outside in. First it calculates the days in the months of each end of the timeline, then the days in each month for each year and then the days in all the years in between. The longer the distance is between the two input dates, the more conditions necessary for the algorithm to calculate the days correctly.
Here, daysCount is the general counter of the days between the two days, which I used throughout my function and eventually what the function returned. I assigned it to the day2 argument. I then subtracted the amount of days in month1 from day1 to get the count of days for the rest of month1. I used the list monthsCommonYear to get the exact amount of days in each month (I tend to leap years later on). This is the first because it occurs in every scenario.
This step returns the result for two input scenarios (I’m using DD/MM/YYYY format here):
- The two input dates have the same year and same month (i.e. 12.8.2012–28.8.2012)
- The two input dates have the same year but sequential months (12.8.2012–15.9.2012)
However, if the input dates are for the same year but the months are different, the function goes to the next step.
In this step, if the months are not sequential and the year is the same, I count the days between the first and the last month (i.e 12.8.2012–24.12.2012)
Here, if the time between the input years is 1 year or more, I add whole months to my daysCount. for year1, I add the next month (month1+1) till the end of the year. For year2, I count months from (month2–1) till the beginning of the year. I take care not to count the days in the months I counted previously. I also take care to count the correct months in my monthsCommonYear list, knowing my arguments can go from 1 to 12, but my list index goes from 0 to 11.
The last step is pretty straightforward. I add to my daysCount the days in each year between year1 and year2. The function eventually returns daysCount.
This exercise had an additional challenge, which made it even more interesting: the function has to tell if a year is common or leap and calculate the days accordingly. It was actually easier than I thought. The Udacity instructions linked to a Wikipedia article that offered the exact algorithm I needed and that was easily converted to a function like the one below.
The comments in this snippet are taken straight from the description in Wikipedia.
I used this function in two types of scenarios:
- To determine which month list to iterate over — leap or common.
- To calculate the amount of days in the last scenario — when there’s a difference of more than 1 year between the two input dates.
I called checkLeapYear() 5 times in my function: 4 times to choose which month list to use (common or leap) and 1 time to add the years to my count. That’s why I preferred checkLeapYear() to return a boolean instead of the number of days in each year (365 or 366).
Here’s the first part of the function, updated to calculate leap years. Notice I added another list for leap year months (the only difference is 29 days in February).
The code I wrote for this exercise is long and encumbered, and perhaps later in my studies I will refactor it to something shorter and more efficient. The important thing for me here was exploring the logic behind the solution, rather than the way it was implemented.