在Python中,如何检查日期是否有效?

问题描述 投票:0回答:11

我正在构建一种日历网络应用程序

我已经在 HTML 中设置了以下表单

<form action='/event' method='post'>
Year ("yyyy"):  <input type='text' name='year' />
Month ("mm"):  <input type='text' name='month' />
Day ("dd"):  <input type='text' name='day' />
Hour ("hh"):  <input type='text' name='hour' />
Description:  <input type='text' name='info' />
             <input type='submit' name='submit' value='Submit'/>
</form>

用户的输入随后被提交到cherrypy服务器中

我想知道,有没有办法检查用户输入的日期是否是有效日期?

显然我可以写很多 if 语句,但是有没有内置函数可以检查这个?

谢谢

python validation date time
11个回答
41
投票

你可以尝试做

import datetime
datetime.datetime(year=year,month=month,day=day,hour=hour)

这将消除诸如月份> 12,小时> 23,不存在的闰日(月份= 2在非闰年最多为28天,否则为29天,其他月份最多为30或31天)(出错时抛出ValueError异常)

您也可以尝试将其与一些理智的上限/下限进行比较。 例如:

datetime.date(year=2000, month=1,day=1) < datetime.datetime(year=year,month=month,day=day,hour=hour) <= datetime.datetime.now()

相关的理智上限和下限取决于您的需求。

编辑:请记住,这不会处理某些可能对您的应用程序无效的日期时间事物(最小生日、假期、营业时间以外的时间等)


34
投票

您可以尝试使用日期时间并处理异常来决定有效/无效日期: 示例:http://codepad.org/XRSYeIJJ

import datetime
correctDate = None
try:
    newDate = datetime.datetime(2008,11,42)
    correctDate = True
except ValueError:
    correctDate = False
print(str(correctDate))

11
投票

这个问题假设没有库的解决方案涉及“大量的 if 语句”,但事实并非如此:

def is_valid_date(year, month, day):
    day_count_for_month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    if year%4==0 and (year%100 != 0 or year%400==0):
        day_count_for_month[2] = 29
    return (1 <= month <= 12 and 1 <= day <= day_count_for_month[month])

7
投票

您可以尝试使用

dateutil.parser
模块来更轻松地进行日期解析:

from dateutil.parser import parse, ParserError

def is_valid_date(date):
    if not date:
        return False
    try:
        parse(date)
        return True
    except ParserError:
        return False

希望这有帮助。


6
投票

使用

datetime

例如。

>>> from datetime import datetime
>>> print datetime(2008,12,2)
2008-12-02 00:00:00
>>> print datetime(2008,13,2)

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    print datetime(2008,13,2)
ValueError: month must be in 1..12

6
投票

您可以尝试使用日期时间并处理异常来决定有效/无效日期:

import datetime

def check_date(year, month, day):
    correctDate = None
    try:
        newDate = datetime.datetime(year, month, day)
        correctDate = True
    except ValueError:
        correctDate = False
    return correctDate

#handles obvious problems
print(str(check_date(2008,11,42)))

#handles leap days
print(str(check_date(2016,2,29)))
print(str(check_date(2017,2,29)))

#handles also standard month length
print(str(check_date(2016,3,31)))
print(str(check_date(2016,4,31)))

给予

False
True
False
True
False

这是 DhruvPathak 的答案的改进,作为编辑更有意义,但它被拒绝为“此编辑旨在向帖子的作者讲话,作为编辑没有任何意义。它应该写成评论或答案。


3
投票
这是一个利用时间的解决方案。

导入时间 def is_date_valid(年、月、日): this_date = '%d/%d/%d' %(月、日、年) 尝试: time.strptime(this_date, '%m/%d/%Y') 除了值错误: 返回错误 别的: 返回真
    

1
投票
所以,这是我纠正所提供的无效日期的黑客解决方案。这假设用户从通用 html 表单提交,该表单提供第 1-31 天作为选项。主要问题是用户提供了当月不存在的某一天(9 月 31 日之前)

def sane_date(year, month, day): # Calculate the last date of the given month nextmonth = datetime.date(year, month, 1) + datetime.timedelta(days=35) lastday = nextmonth.replace(day=1) - datetime.timedelta(days=1) return datetime.date(year, month, min(day, lastday.day)) class tests(unittest.TestCase): def test_sane_date(self): """ Test our sane_date() method""" self.assertEquals(sane_date(2000,9,31), datetime.date(2000,9,30)) self.assertEquals(sane_date(2000,2,31), datetime.date(2000,2,29)) self.assertEquals(sane_date(2000,1,15), datetime.date(2000,1,15))
    

0
投票
y = int(input("Year: ")) m = int(input("Month: ")) d = int(input("Day: ")) if 0 <= y and 0 < m < 13 and 0 < d < 32: #Check whether date is under limit. if y % 4 == 0: # Every 4 year "Leap" year occures so checking... if m == 2: # In "Leap" year February has 29 days if d < 30: print("<Correct>") else: print("<Wrong>") elif m == 2: # But if it's not "Leap" year February will have 28 days if d < 29: print("<Correct>") else: print("<Wrong>") elif y % 4 != 0 and m != 2: # Otherwise print "Correct" print("<Correct>") else: print("<Wrong>")
    

0
投票
基于@codehia答案,以下内容还允许检查日期的格式,并将字符串拆分为年,月,日 - 所有上述假设都已经有年,月,日。

from dateutil.parser import parse import string p=print space_punct_dict = dict((ord(punct), ' ') for punct in string.punctuation) def is_valid_date_p(date): if date: try: date = date.translate(space_punct_dict) new_date = str(parse(date))[:10] year = new_date[:4] month = new_date[5:7] day = new_date[8:] p(year, month, day) return True, year, month, day except: p('invalid:', date) return False return False year, month, day = 2021, 6, 1 is_valid_date_p(f'{month}/{day}/{year}') is_valid_date_p(f'{month}.{day}.{year}') is_valid_date_p(f'{month},{day},{year}') is_valid_date_p(f'{month}/{day}/{year}') is_valid_date_p(f'{month}-{day}-{year}') is_valid_date_p(f'{month} {day} {year}') p() is_valid_date_p('12/1/20') is_valid_date_p('12/31/20') p() is_valid_date_p('31/12/20') is_valid_date_p('30/6/2020') is_valid_date_p('2020/30/6')
输出:

2021 06 01

2021 06 01

2021 06 01

2021 06 01

2021 06 01

2021 06 01

2020年12月01日

2020年12月31日

2020年12月31日

2020年06月30日

无效:2020年30月6日


0
投票
就个人而言,我主要使用

deteutil.parser

,它可以在解析日期时简化代码。通过此代码片段,您还可以捕获无效日期:

import dateutil.parser input_date = '2022-06-30' try: result_date = dateutil.parser.parse(input_date, dayfirst=True).strftime('%Y-%m-%d') except dateutil.parser._parser.ParserError as ex: print(ex) # handle the exception from here on
其中 

strftime('%Y-%m-%d')

 部分固定输出格式。如果没有该方法,即仅 
result_date = dateutil.parser.parse(input_date, dayfirst=True)
,它会返回一个日期时间对象。可选的 
dayfirst=True
 会省略像 
3/6/2022
 这样不明确的日期,将被解析为 6 月 3 日(而不是 3 月 6 日)。

让我们尝试一些不同格式的输入,甚至添加一些垃圾:

multiple_inputs = ['2022-06-30', '30/6/2022', '30 06 2022', '3/6/2022', '2022-06-31', '2022-15-30', '', 'garbage'] for input_date in multiple_inputs: try: result_date = dateutil.parser.parse(input_date, dayfirst=True).strftime('%Y-%m-%d') print(f'Valid date: {result_date}') except dateutil.parser._parser.ParserError as ex: print(ex)
这给出了:

Valid date: 2022-06-30 Valid date: 2022-06-30 Valid date: 2022-06-30 Valid date: 2022-06-03 day is out of range for month: 2022-06-31 month must be in 1..12: 2022-15-30 String does not contain a date: Unknown string format: garbage
    
© www.soinside.com 2019 - 2024. All rights reserved.