Może być bardziej Pythonic (poproś o wybaczenie, a nie pozwolenie), aby w ogóle nie sprawdzać i wychwytywać wszelkie wynikające z tego wyjątki, które wystąpią.
>>>import datetime
>>>def validate(date_text):try:
datetime.datetime.strptime(date_text,'%Y-%m-%d')exceptValueError:raiseValueError("Incorrect data format, should be YYYY-MM-DD")>>> validate('2003-12-23')>>> validate('2003-12-32')Traceback(most recent call last):File"<pyshell#20>", line 1,in<module>
validate('2003-12-32')File"<pyshell#18>", line 5,in validate
raiseValueError("Incorrect data format, should be YYYY-MM-DD")ValueError:Incorrect data format, should be YYYY-MM-DD
Czy można to zrobić bez próby / z wyjątkiem? Python ma tendencję do znacznego spowolnienia, gdy wyjątek jest zgłaszany i przechwytywany.
chiffa
1
@chiffa Możesz dopasować wyrażenie regularne w formacie daty, ale nie jest to zalecane, ponieważ jest mniej niezawodne, a wyjątki są wyraźniejsze. Czy na pewno walidacja daty jest Twoim wąskim gardłem?
jamylak
1
Niezupełnie, więc na koniec po prostu zawijam konstrukcję rzutowania z wyjątkiem funkcji. Jestem po prostu zaskoczony, że nie ma funkcji walidującej zwracającej wartość bool, która wyzwoliłaby rzut wyjątku w bibliotece datetime.
chiffa
@chiffa Może celowo nie uwzględnili funkcji bool zwracającej funkcję walidacji, może ona istnieć w bibliotekach zewnętrznych
jamylak
2
Dla tych, którzy chcą dopełnienia zerami w datach, to rozwiązanie nie zadziała, ponieważ strptime nie wymaga ścisłego uzupełniania zer. Zaimplementuj własne wyrażenie regularne lub sprawdź długość powstałego ciągu znaków po usunięciu białych znaków, a następnie skorzystaj z tego rozwiązania.
Suparshva
65
Pythondateutil biblioteka jest przeznaczony do tego (i więcej). Automatycznie przekształci to w datetimeobiekt dla ciebie i podniesie, ValueErrorjeśli nie może.
Wiąże się ValueErrorto z nieprawidłowym formatowaniem daty:
>>> parse("2003-09-251")Traceback(most recent call last):File"<stdin>", line 1,in<module>File"/Users/jacinda/envs/dod-backend-dev/lib/python2.7/site-packages/dateutil/parser.py", line 720,in parse
return DEFAULTPARSER.parse(timestr,**kwargs)File"/Users/jacinda/envs/dod-backend-dev/lib/python2.7/site-packages/dateutil/parser.py", line 317,in parse
ret = default.replace(**repl)ValueError: day is out of range for month
dateutiljest również niezwykle przydatny, jeśli w przyszłości będziesz musiał analizować inne formaty, ponieważ może inteligentnie obsługiwać większość znanych formatów i umożliwia modyfikowanie specyfikacji: dateutilanalizowanie przykładów .
Obsługuje również strefy czasowe, jeśli tego potrzebujesz.
Aktualizacja oparta na komentarzach : parseakceptuje również argument słowa kluczowego, dayfirstktóry kontroluje, czy dzień lub miesiąc ma być pierwszy, jeśli data jest niejednoznaczna. Domyślnie jest to False. Na przykład
>>> parse('11/12/2001')>>> datetime.datetime(2001,11,12,0,0)# Nov 12>>> parse('11/12/2001', dayfirst=True)>>> datetime.datetime(2001,12,11,0,0)# Dec 11
może przyjąć za dużo, np. parse('13/12/2001')„13 grudnia”, ale parse('11/12/2001')„12 listopada” (pierwszy wynik sugerowałby tutaj „11 grudnia”).
jfs
2
parsew rzeczywistości przyjmuje dayfirstargument słowa kluczowego, który pozwala ci to kontrolować. parse('11/12/2001', dayfirst=True)zwróci „11 grudnia”. Dateutil domyślnie todayfirst=False
Jacinda
brakuje Ci punktu, który datetutil.parser.parse()akceptuje zbyt wiele formatów czasu (możesz znaleźć inne przykłady z niejednoznacznymi danymi wejściowymi). Jeśli chcesz sprawdzić , czy wprowadzone dane są w formacie RRRR-MM-DD, parse()funkcja jest niewłaściwym narzędziem.
jfs
1
To całkowicie słuszna uwaga - jeśli naprawdę chcesz ograniczyć się tylko do tego konkretnego formatu, to tego nie robi, a zaakceptowana odpowiedź już robi świetną robotę, robiąc właściwą rzecz w tym przypadku. Myślę, że kiedy pisałem odpowiedź, myślałem bardziej o wskazaniu, jak sprawdzić, czy była to ważna data, w przeciwieństwie do konkretnego formatu, o który prosił autor, który, gdy ludzie napotykają to pytanie, jest tym, co często szukam.
Jacinda
Czy istnieje sposób na .parse()zwrócenie ciągu formatu oprócz datetimeobiektu?
citynorman
35
Myślę, że pełna funkcja walidacji powinna wyglądać tak:
from datetime import datetime
def validate(date_text):try:if date_text != datetime.strptime(date_text,"%Y-%m-%d").strftime('%Y-%m-%d'):raiseValueErrorreturnTrueexceptValueError:returnFalse
Wykonywanie tylko
datetime.strptime(date_text,"%Y-%m-%d")
nie wystarczy, ponieważ metoda strptime nie sprawdza, czy miesiąc i dzień miesiąca są liczbami dziesiętnymi uzupełnionymi zerami. Na przykład
„Jesteś poprawny technicznie - najlepszy rodzaj poprawności”. Musiałem to zapewnić w moich strunach.
delrocco
Działa to dobrze w przypadku moich testów, jednak dokumentacja wydaje się niepoprawna, ponieważ stwierdza: "% d -> Dzień miesiąca jako liczba dziesiętna z zerami -> 01, 02,…, 31" i to samo dla% m -> Miesiąc jako liczba dziesiętna z zerami. -> 01, 02,…, 12 docs.python.org/2/library/…
thanos.a
Jeśli chcesz sprawdzić, czy miesiąc i dzień są wypełnione zerami, czy nie wystarczyłoby po prostu sprawdzić długość ciągu i datetime.strptime(date_text, "%Y-%m-%d")?
Kyle Barron
17
from datetime import datetime
datetime.strptime(date_string,"%Y-%m-%d")
.. wywołuje to, ValueErrorjeśli otrzyma niezgodny format.
..jeśli masz do czynienia z datami i czasami (w sensie obiektów datetime, w przeciwieństwie do unx timestamp float), dobrym pomysłem jest zajrzenie do modułu pytz i przechowywanie / db, przechowywanie wszystkiego w UTC .
Odpowiedzi:
źródło
Python
dateutil
biblioteka jest przeznaczony do tego (i więcej). Automatycznie przekształci to wdatetime
obiekt dla ciebie i podniesie,ValueError
jeśli nie może.Jako przykład:
Wiąże się
ValueError
to z nieprawidłowym formatowaniem daty:dateutil
jest również niezwykle przydatny, jeśli w przyszłości będziesz musiał analizować inne formaty, ponieważ może inteligentnie obsługiwać większość znanych formatów i umożliwia modyfikowanie specyfikacji:dateutil
analizowanie przykładów .Obsługuje również strefy czasowe, jeśli tego potrzebujesz.
Aktualizacja oparta na komentarzach :
parse
akceptuje również argument słowa kluczowego,dayfirst
który kontroluje, czy dzień lub miesiąc ma być pierwszy, jeśli data jest niejednoznaczna. Domyślnie jest to False. Na przykładźródło
parse('13/12/2001')
„13 grudnia”, aleparse('11/12/2001')
„12 listopada” (pierwszy wynik sugerowałby tutaj „11 grudnia”).parse
w rzeczywistości przyjmujedayfirst
argument słowa kluczowego, który pozwala ci to kontrolować.parse('11/12/2001', dayfirst=True)
zwróci „11 grudnia”. Dateutil domyślnie todayfirst=False
datetutil.parser.parse()
akceptuje zbyt wiele formatów czasu (możesz znaleźć inne przykłady z niejednoznacznymi danymi wejściowymi). Jeśli chcesz sprawdzić , czy wprowadzone dane są w formacie RRRR-MM-DD,parse()
funkcja jest niewłaściwym narzędziem..parse()
zwrócenie ciągu formatu opróczdatetime
obiektu?Myślę, że pełna funkcja walidacji powinna wyglądać tak:
Wykonywanie tylko
nie wystarczy, ponieważ metoda strptime nie sprawdza, czy miesiąc i dzień miesiąca są liczbami dziesiętnymi uzupełnionymi zerami. Na przykład
zostanie wykonany bez błędów.
źródło
datetime.strptime(date_text, "%Y-%m-%d")
?.. wywołuje to,
ValueError
jeśli otrzyma niezgodny format...jeśli masz do czynienia z datami i czasami (w sensie obiektów datetime, w przeciwieństwie do unx timestamp float), dobrym pomysłem jest zajrzenie do modułu pytz i przechowywanie / db, przechowywanie wszystkiego w UTC .
źródło
To najłatwiejszy sposób:
źródło