Jak sprawdzić, czy ciąg może być analizowany na datę?

  • 19 stycznia 1990 r
  • 19 stycznia 1990 r
  • Jan 19,1990.
  • 01/19/1990.
  • 01/19/90.
  • 1990.
  • Jan 1990.
  • Styczeń1990.

Są to wszystkie ważne daty. Jeśli istnieje jakaś obawa w odniesieniu do braku miejsca między materiałami w pozycji # 3, a ostatni element powyżej, można go łatwo naprawić za pomocą automatycznego wkładania przestrzeni między literami / znakami i liczbami, jeśli tak jest potrzebne.

Ale najpierw podstawy:

Próbowałem umieścić go w if statement:

if datetime.strptime(item, '%Y') or datetime.strptime(item, '%b %d %y') or datetime.strptime(item, '%b %d %Y')  or datetime.strptime(item, '%B %d %y') or datetime.strptime(item, '%B %d %Y'):

Ale to z wyjątkiem bloku, i nadal zwraca coś takiego:

16343 time data 'JUNE1890' does not match format '%Y'

Chyba że spełnił pierwszy stan w oświadczeniu if.

Aby wyjaśnić, nie potrzebuję wartości daty - chcę tylko wiedzieć, jeśli tak jest. Idealnie byłoby to coś takiego:

if item is date:
    print date
else:
    print "Not a date"

Czy jest na to sposób?

74
zack_falcon 16 sierpień 2014, 21:03

2 odpowiedzi

Najlepsza odpowiedź

parse funkcja w {X1}} jest zdolny do analizowania wielu formatów ciągów daty do obiektu {x2}}.

Jeśli po prostu chcesz wiedzieć, czy konkretny ciąg może reprezentować lub zawierać prawidłową datę, możesz wypróbować następującą prostą funkcję:

from dateutil.parser import parse

def is_date(string, fuzzy=False):
    """
    Return whether the string can be interpreted as a date.

    :param string: str, string to check for date
    :param fuzzy: bool, ignore unknown tokens in string if True
    """
    try: 
        parse(string, fuzzy=fuzzy)
        return True

    except ValueError:
        return False

W takim razie masz:

>>> is_date("1990-12-1")
True
>>> is_date("2005/3")
True
>>> is_date("Jan 19, 1990")
True
>>> is_date("today is 2019-03-27")
False
>>> is_date("today is 2019-03-27", fuzzy=True)
True
>>> is_date("Monday at 12:01am")
True
>>> is_date("xyz_not_a_date")
False
>>> is_date("yesterday")
False

Niestandardowy parsowanie

parse może rozpoznać niektóre struny jako daty, których nie chcesz traktować jako daty. Na przykład:

  • Parsowanie "12" i "1999" zwróci obiekt DATETIME reprezentujący bieżący datę z dniem i rokiem podstawionym liczbą w ciągu

  • "23, 4" i "23 4" będą analizowane jako datetime.datetime(2023, 4, 16, 0, 0).

  • "Friday" zwróci datę najbliższego piątku w przyszłości.
  • Podobnie "August" odpowiada bieżącą datę z miesiącem zmienionym na sierpień.

Również parse nie jest świadomy, więc nie rozpoznaje miesięcy ani dni tygodnia w językach innych niż angielski.

Oba te problemy mogą być adresowane do pewnego stopnia, używając niestandardowej { {X0}} klasa, która określa, jak miesiąc i nazwiska są rozpoznawane:

from dateutil.parser import parserinfo

class CustomParserInfo(parserinfo):

    # three months in Spanish for illustration
    MONTHS = [("Enero", "Enero"), ("Feb", "Febrero"), ("Marzo", "Marzo")]

Instancja tej klasy może być następnie użyta z parse:

>>> parse("Enero 1990")
# ValueError: Unknown string format
>>> parse("Enero 1990", parserinfo=CustomParserInfo())
datetime.datetime(1990, 1, 27, 0, 0)
108
Alex Riley 27 marzec 2019, 12:22

Jeśli chcesz analizować te konkretne formaty, możesz po prostu dopasować do listy formatów:

txt='''\
Jan 19, 1990
January 19, 1990
Jan 19,1990
01/19/1990
01/19/90
1990
Jan 1990
January1990'''

import datetime as dt

fmts = ('%Y','%b %d, %Y','%b %d, %Y','%B %d, %Y','%B %d %Y','%m/%d/%Y','%m/%d/%y','%b %Y','%B%Y','%b %d,%Y')

parsed=[]
for e in txt.splitlines():
    for fmt in fmts:
        try:
           t = dt.datetime.strptime(e, fmt)
           parsed.append((e, fmt, t)) 
           break
        except ValueError as err:
           pass

# check that all the cases are handled        
success={t[0] for t in parsed}
for e in txt.splitlines():
    if e not in success:
        print e    

for t in parsed:
    print '"{:20}" => "{:20}" => {}'.format(*t) 

Wydruki:

"Jan 19, 1990        " => "%b %d, %Y           " => 1990-01-19 00:00:00
"January 19, 1990    " => "%B %d, %Y           " => 1990-01-19 00:00:00
"Jan 19,1990         " => "%b %d,%Y            " => 1990-01-19 00:00:00
"01/19/1990          " => "%m/%d/%Y            " => 1990-01-19 00:00:00
"01/19/90            " => "%m/%d/%y            " => 1990-01-19 00:00:00
"1990                " => "%Y                  " => 1990-01-01 00:00:00
"Jan 1990            " => "%b %Y               " => 1990-01-01 00:00:00
"January1990         " => "%B%Y                " => 1990-01-01 00:00:00
13
dawg 17 sierpień 2014, 16:46