【问题标题】:In python, how to check if a date is valid?在python中,如何检查日期是否有效?
【发布时间】:2012-04-16 18:51:20
【问题描述】:

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

我已经在 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


【解决方案1】:

你可以试试

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

这将消除月份 >12 ,小时 > 23 ,不存在的闰日(month=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()

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      问题假设没有库的解决方案涉及“大量的 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])
      

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 但这不会给我一个错误信息吗?并导致一切崩溃?我希望是否有一个函数,例如,如果它是有效日期则返回 1,如果它无效则返回 0。然后我可以提示用户在网页中重新输入日期。
        • 或者您可以try...except 并捕获错误。然后你可以做你想做的事,如果你愿意的话,默默地传递错误。
        【解决方案5】:

        您可以尝试使用dateutil.parser 模块来简化日期解析:

        from dateutil.parser import parse
        def is_valid_date(date):
            if date:
                try:
                    parse(date)
                    return True
                except:
                    return False
            return False
        

        希望这会有所帮助。

        【讨论】:

          【解决方案6】:

          这是一个使用时间的解决方案。

          进口时间
          def is_date_valid(年、月、日):
              this_date = '%d/%d/%d' %(月、日、年)
              尝试:
                  time.strptime(this_date, '%m/%d/%Y')
              除了ValueError:
                  返回假
              别的:
                  返回真
          

          【讨论】:

          • 你为什么要这么做而不是date(year, month, day)
          【解决方案7】:

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

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

          gives

          False
          True
          False
          True
          False
          

          这是对an answer by DhruvPathak 的改进,作为编辑更有意义,但它被拒绝为“This edit was intended to address the author of the post and makes no sense as an edit. It should have been written as a comment or an answer.

          【讨论】:

            【解决方案8】:

            所以,这是我纠正提供的无效日期的 hacky 解决方案。这假设用户从提供第 1-31 天作为选项的通用 html 表单提交。主要问题是用户提供了当月不存在的一天(例如 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))
            

            【讨论】:

              【解决方案9】:
              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>")
              

              【讨论】:

              • 最好提供一些解释
              • 虽然这可能会回答作者的问题,但它缺少一些解释性文字和文档链接。如果没有围绕它的一些短语,原始代码 sn-ps 并不是很有帮助。您可能还会发现how to write a good answer 非常有帮助。请编辑您的答案。
              【解决方案10】:

              在@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 月 1 日

              2020 年 12 月 31 日

              2020 年 12 月 31 日

              2020 年 06 月 30 日

              无效:2020 30 6

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2017-02-28
                • 2020-01-24
                • 1970-01-01
                • 2012-03-15
                • 1970-01-01
                • 1970-01-01
                • 2023-02-22
                • 1970-01-01
                相关资源
                最近更新 更多