Python, валидация даты - PullRequest
       7

Python, валидация даты

4 голосов
/ 10 сентября 2011

Я пытаюсь придумать, как это сделать наилучшим образом. Прямо сейчас единственный способ, который я могу придумать, - это перебор.

Пользователь вводит дату (через командную строку) одним из следующих способов (например, ./mypy.py date = '20110909.00 23')

date='20110909'
date='20110909.00 23'
date='20110909.00 20110909.23'

Все три примера должны иметь одинаковый результат, не имеет значения, заполняет ли он список (который я могу отсортировать), например

['20110909.00', '20110909.23]

или даже две отсортированные отдельные переменные, но во всех случаях это ГГГГММДД.ЧЧ, и необходимо убедиться, что это действительно дата, а не текст.

Есть идеи?

Спасибо.

+++++ EDIT +++++ Подумав об этом, я думаю, что сначала мне нужно было сделать много проверок / манипуляций с датами. Который, кажется, работает просто великолепно. За исключением самого конца, я проверяю список по проверке даты, и он каждый раз терпит неудачу - даже когда он должен проходить.

(я запускаю его с) ./test.py date = '20110909,00 23'

(или любое изменение даты - т.е. дата = '20 22' или дата = '20110909' или дата = '20110909.00 23' и т. Д.)

import sys, re, time, datetime

now = datetime.datetime.now()
tempdate=[]
strfirstdate=None
strtempdate=None

temparg2 = sys.argv
del temparg2[0]
tempdate = temparg2[0].replace('date=','')
date = tempdate.split(' ');

tempdate=[]
date.sort(key=len, reverse=True)
result = None

# If no date is passed then create list according to [YYMMDD.HH, YYMMDD.HH]
if date[0] == 'None':
    tempdate.extend([now.strftime('%Y%m%d.00'), now.strftime('%Y%m%d.%H')])


# If length of date list is 1 than see if it is YYMMDD only or HH only, and create list according to [YYMMDD.HH, YYMMDD.HH]
elif len(date) == 1:
    if len(date[0]) == 8:
        tempdate.extend([ date[0] + '.00', date[0] + '.23'])
    elif len(date[0]) == 2:
        tempdate.extend([now.strftime('%Y%m%d') + '.' + date[0], now.strftime('%Y%m%d') + '.' + date[0]])
    else:
        tempdate.extend([date[0], date[0]])


# iterate through list, see if value is YYMMDD only or HH only or YYYYMMDD.HH, and create list accoring to [YYYYMMDD.HH, YYYYMMDD.HH] - maximum of 2 values
else:
    for _ in range(2):
        if len(date[_]) == 8:
            strfirstdate = date[0]
            tempdate.append([ date[_] + '.00'])
        elif len(date[_]) == 2:
            if _ == 0:  # both values passed could be hours only
                tempdate.append(now.strftime('%Y%m%d') + '.' + date[_])
            else:  # we must be at the 2nd value passed.
                if strfirstdate == None:
                    tempdate.append(now.strftime('%Y%m%d') + '.' + date[_])
                else:
                    tempdate.append(strfirstdate + '.' + date [_])
        else:
            strfirstdate = date[0][:8]
            tempdate.append(date[_])

tempdate.sort()


for s in tempdate:
    try:
        result = datetime.datetime.strptime(s, '%Y%m%d.%H')
    except:
        pass

if result is None:
    print 'Malformed date.'
else:
    print 'Date is fine.'

print tempdate

++++ Редактировать 2 ++++ Если я удаляю нижнюю часть (после tempdate.sort ()) и заменяю ее следующим:

strfirstdate = re.compile(r'([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]+\.[0-9][0-9])')
for s in tempdate:
    if re.match(strfirstdate, s):
        result = "validated"
    else:
        print "#####################"
        print "#####################"
        print "##  error in date  ##"
        print "#####################"
        print "#####################"
        exit

Это будет подтверждено соответствующим образом.

Весь этот метод не выглядит слишком питоническим.

Ответы [ 4 ]

7 голосов
/ 10 сентября 2011

Вы можете создать маску и проанализировать ее, используя try...except, чтобы определить, соответствует ли строка даты одной из множества масок.У меня был этот код для проекта, поэтому я немного изменил его:

from time import mktime, strptime
from datetime import datetime

date = '20110909.00 20110909.23'.split(' ')[0]
result = None

for format in ['%Y%m%d', '%Y%m%d.%H']:
  try:
    result = datetime.strptime(date, format)
  except:
    pass

if result is None:
  print 'Malformed date.'
else:
  print 'Date is fine.'
1 голос
/ 25 декабря 2011

Я обнаружил некоторые проблемы, когда попытался использовать пример кода try..except в моем собственном анализе, поэтому вот версия с добавленными мною исправлениями, а также я рассмотрел вопрос обработки только часовой части:

from datetime import datetime

dates = ['20110909.00','20110909.23','13','20111212','20113131']

def dateTest(date):
  dateOk = False
  for format in ['%Y%m%d', '%Y%m%d.%H', '%H']:
    try:
      result = datetime.strptime(date, format)
      dateOk = (date == result.strftime(format)) # this makes sure the parsed date matches the original string
      if format == '%H': # this handles the hour only case
        date = '%s.%s' % (datetime.now().strftime('%Y%m%d'), date)
    except:
      pass

  if dateOk:
    print 'Date is fine.'
  else:
    print 'Malformed date.'
  return date

for date in dates:
  print date
  print dateTest(date)
  print ''
0 голосов
/ 10 сентября 2011

Вам это помогает? :

from datetime import datetime
import re

reg = re.compile('(\d{4})(\d\d)(\d\d)'
                 '(?:\.(\d\d)(\d\d)?(\d\d)? *'
                 '(?:(\d{4})(\d\d)(\d\d)\.)?(\d\d)(\d\d)?(\d\d)? *)?')

for x in ('20110909',
          '20110909.00 23',
          '20110909.00 74',
          '20110909.00 20110909.23',
          '20110909.00 19980412.23',
          '20110909.08 20110909.23',
          '20110935.08 20110909.23',
          '20110909.08 19970609.51'):
    print x

    gr = reg.match(x).groups('000')

    try:
        x1 = datetime(*map(int,gr[0:6]))

        if gr[6]=='000':

            if gr[9]=='000':
                x2 = x1

            else:
                y = map(int,gr[0:3] + gr[9:12])
                try:
                    x2 = datetime(*y)
                except:
                    x2 = "The second part isn't in range(0,25)"

        else:
            y = map(int,gr[6:12])
            try:
                x2 = datetime(*y)
            except:
                x2 = "The second part doesn't represent a real date"
    except:
        x1 = "The first part dosen't represent a real date"
        x2 = '--'

    print [str(x1),str(x2)],'\n'

результат

20110909
['2011-09-09 00:00:00', '2011-09-09 00:00:00'] 

20110909.00 23
['2011-09-09 00:00:00', '2011-09-09 23:00:00'] 

20110909.00 74
['2011-09-09 00:00:00', "The hour in the second part isn't in range(0,25)"] 

20110909.00 20110909.23
['2011-09-09 00:00:00', '2011-09-09 23:00:00'] 

20110909.00 19980412.23
['2011-09-09 00:00:00', '1998-04-12 23:00:00'] 

20110909.08 20110909.23
['2011-09-09 08:00:00', '2011-09-09 23:00:00'] 

20110935.08 20110909.23
["The first part dosen't represent a real date", '--'] 

20110909.08 19970609.51
['2011-09-09 08:00:00', "The second part doesn't represent a real date"]  

.

Обратите внимание, что groups('000') заменить Нет на '000' для каждой группы, Нет

0 голосов
/ 10 сентября 2011

Посмотрите на модуль time .В частности, смотрите функцию time.strptime () .

Существует также довольно простое преобразование между значениями времени и объектами datetime.

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