1

Hi I'm a beginner at Python and am currently using Python 3.4.1 on PyCharm. I have recently made a project that calculates the amount of days between 2 dates, but there are 2 problems.

def get_first_day():
    while True:
        try:
            print('First Date')
            day = int(input('Day:'))
            month = int(input('Month:'))
            year = int(input('Year:'))
            print(day, '/', month, '/', year)
            date = [day, month, year * 365]
            get_second_day(date)
        except ValueError:
            print('You were supposed to enter a date.')

 def get_second_day(date_1):
    while True:
       try:
           print('Second Date')
           day = int(input('Day:'))
           month = int(input('Month:'))
           year = int(input('Year:'))
           print(day, '/', month, '/', year)
           date = [day, month, year * 365]
           convert_dates_and_months(date_1, date)
       except ValueError:
           print('You were supposed to enter a date.')


def convert_dates_and_months(date_1, date_2):
    days_unfiltered = [date_1[0], date_2[0]]
    months_unfiltered = [date_1[1], date_2[1]]
    year = [date_1[2], date_2[2]]
    date_unfiltered = zip(days_unfiltered, months_unfiltered, year)
    for d, m, y in date_unfiltered:
        if m in [1, 3, 5, 7, 8, 10, 12]:
            a = 31
        elif m in [4, 6, 9, 11]:
            a = 30
        elif m in [2, 0] and int(y) % 4 is 0:
            a = 29
        else:
            a = 28
        m *= a
    days = list(filter(lambda x: 0 < x < (a + 1), days_unfiltered))
    months = list(filter(lambda x: 0 < x < 13, months_unfiltered))
    date_1 = [days[0], months[0], year[0]]
    date_2 = [days[1], months[1], year[1]]
    determine_date_displacement(date_1, date_2)


def determine_date_displacement(date_1, date_2):
    full_dates = zip(date_1, date_2)
    days = -1
    for k, v in full_dates:
        days += (int(v) - int(k))
    if days < 0:
        days *= -1
    print(days)


get_first_day()

The first problem is that the counter returns an incorrect number of days between 2 dates. The second is that def get_second_day repeats at the end for some reason. I'll show you what I mean:

First Date
Day:10
Month:09
Year:03
10 / 9 / 3

Second Date
Day:06
Month:06
Year:06
6 / 6 / 6

1087

Second Date
Day:

I know for a fact there are exactly 1,000 days between 10/09/03 and 06/06/06, yet the project returns 1,087 days.

If anyone could explain why this project is returning an incorrect number, as well as why it asks me to fill the second date again at the end, that would be perfect.

As this is my first question and I'm a beginner at Python, I apologise in advance for any weird phrasing/bad practices seen in this question.

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69

1 Answers1

3

Problem 1:

Your leap year calculation is off:

Leap years are years % 4 == 0 but only for years not year % 100 == 0 unless they are also year % 400 == 0:

2004,2008,2012 : leap year (%4==0, not %100==0)
1700,1800,1900 : no leap year (%4 == 0 , % 100 == 0 but not %400 == 0)
1200,1600,2000 : leap years (* 1200 theor. b/c gregorian cal start)

Problem 2:

In your input you premultiply the year by 365 w/o checking for leap-years - they schould have 366 days but got 365 - which would result in lacking days when computing the amount of days for years that leap(ed).

Problem 3:

You have a controlflow-issue: the get_second_day() repeats because you do:

get_first_date()
    while without end:
        do smth
        call get_second_date(..)
             while without end:
                 do smth 
                 call some calculation functions
                     that calc and print and return with None 
                 back in get_second_date(), no break, so back to the beginning
                 of its while and start over forever - you are TRAPPED
  • fix it by putting a break after convert_dates_and_months(date_1, date) inside get_second_day(..)

Suggestions:

You can streamline the input by reducing the amount of duplicate code between get_first_day() and get_second_day() - this follows the DRY principle (Don't Repeat Yourself):

def getDate(text):
    while True:
        try:
            print(text)
            day = int(input('Day:'))
            month = int(input('Month:'))
            year = int(input('Year:'))
            print(day, '/', month, '/', year)
            return [day, month, year * 365]  # see Problem 2
        except ValueError:
            print('You were supposed to enter a date.')


def get_first_day():
    date1 = getDate("First Date")
    # rest of code omitted 

def get_second_day(date_1):
    date = getDate("Second Date")
    # rest of code omitted 

A better solution would utilize datetime and datettime-parsing, especially if you want to handle input validation and leap-year estimation you would need far more checks.

Using datetime module would simplyfy this a lot:

import datetime

def getDate(text):
    while True:
        try:
            print(text)
            day = int(input('Day:'))
            month = int(input('Month:'))
            year = int(input('Year (4 digits):'))
            print(day, '/', month, '/', year)

            # this will throw error on invalid dates: 
            # f.e. 66.22.2871 or even (29.2.1977) and user
            # gets a new chance to input something valid
            return datetime.datetime.strptime("{}.{}.{}".format(year,month,day),"%Y.%m.%d")
        except (ValueError,EOFError):
            print('You were supposed to enter a valid date.')


def get_first_day():
    return getDate("First Date")

def get_second_day():
    return getDate("Second Date")

# while True: # uncomment and indent next lines to loop endlessly
first = get_first_day()     # getDate("First Date") and getDate("Second Date") 
second = get_second_day()   # directly would be fine IMHO, no function needed
print( (second-first).days) 

Output:

First Date
Day:10
Month:9
Year (4 digits):2003
10 / 9 / 2003
Second Date
Day:6
Month:6
Year (4 digits):2006
6 / 6 / 2006
1000 

Good read: How to debug small programs (#1) - following it, could have at least lead you to the control-flow issue.

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69