Почему этот день счетчик дает неправильные результаты? - PullRequest
0 голосов
/ 09 июня 2018

Привет, я новичок в Python и в настоящее время использую Python 3.4.1 в PyCharm.Недавно я создал проект, который вычисляет количество дней между двумя датами, но есть две проблемы:

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()

Первая проблема заключается в том, что счетчик возвращает неверное количество дней между двумя датами.Во-вторых, почему-то def get_second_day повторяется в конце.Я покажу вам, что я имею в виду:

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:

Я точно знаю, что между 10/09/03 и 06/06/06 ровно 1000 дней, но проект возвращается 1087 дней.

Если бы кто-нибудь мог объяснить, почему этот проект возвращает неправильный номер, а также почему он просит меня снова заполнить вторую дату в конце, это было бы идеально.

Так как этоМой первый вопрос, и я новичок в Python, заранее прошу прощения за любые странные фразы / плохие практики, встречающиеся в этом вопросе.

1 Ответ

0 голосов
/ 09 июня 2018

Задача 1:

Ваш расчет високосного года выключен:

Високосные годы years % 4 == 0, но только для лет, не year % 100 == 0, если только они не 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)

Задача 2:

В своем вводе вы предварительно умножаете год на 365 без проверки високосных лет - у них должно быть 366 дней, но получается 365 - что приведет к отсутствию дней при вычисленииколичество дней в годах, которые прыгают (ред.).

Проблема 3:

У вас возникла проблема с потоком управления: get_second_day() повторяется, потому что вы делаете:

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
  • исправить это, поставив break после convert_dates_and_months(date_1, date) внутри get_second_day(..)

Предложения:

Вы можете оптимизироватьввод, уменьшая количество повторяющегося кода между get_first_day() и get_second_day() - это следует принципу СУХОЙ ( D на R epeat Y самим):

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 

Лучшее решение будет использовать datetime и datettime-parsing , особенно если вы хотите обработать проверку ввода иДля оценки високосного года вам понадобится гораздо больше проверок.

Использование модуля datetime очень просто:

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) 

Вывод:

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 

Хорошее чтение: Как отлаживать небольшие программы (# 1) - после этого, по крайней мере, может привести вас к проблеме потока управления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...