为什么这一天的柜台会产生错误的结果?

时间:2018-06-09 09:53:24

标签: python python-3.x calendar pycharm

您好,我是Python的初学者,目前正在PyCharm上使用Python 3.4.1。我最近做了一个计算两个日期之间的天数的项目,但有两个问题。

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之间恰好有1,000天,但该项目返回1,087天。

如果有人能够解释为什么这个项目返回的数字不正确,以及为什么要求我在最后再次填写第二个日期,那将是完美的。

由于这是我的第一个问题而且我是Python的初学者,所以我提前为这个问题中出现的任何奇怪的措辞/不良做法道歉。

1 个答案:

答案 0 :(得分:3)

问题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 w / o检查闰年 - 他们可能有366天但是有365天 - 这将导致计算跳跃(ed)年数的天数缺乏。

问题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()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 之间重复代码的数量来简化输入 - 这遵循DRY原则( D on't R < / strong> epeat Y 我们自己):

datetime

更好的解决方案是使用datetime and datettime-parsing,特别是如果您想要处理输入验证和闰年估算,则需要更多检查。

使用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 

输出:

0x

好读:How to debug small programs (#1) - 跟着它,至少可以引导你解决控制流问题。