Python'da tarih dizesi biçimini nasıl doğrularım?


143

Dize olarak bir tarih girişi kabul eden bir python yöntemi var .

Yönteme iletilen tarih dizesinin ffg'de olduğundan emin olmak için nasıl doğrulama ekleyebilirim? biçim:

'YYYY-MM-DD'

değilse, yöntem bir tür hata ortaya çıkarmalıdır


2
Hiç kontrol etmemek ve ortaya çıkan istisnaları yakalamak daha Pythonic (affetmeyi isteyin, izin istemeyin) olabilir.
Thomas

Yanıtlar:


230
>>> import datetime
>>> def validate(date_text):
    try:
        datetime.datetime.strptime(date_text, '%Y-%m-%d')
    except ValueError:
        raise ValueError("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
    raise ValueError("Incorrect data format, should be YYYY-MM-DD")
ValueError: Incorrect data format, should be YYYY-MM-DD

8
Bunu denemeden / hariç yapmanın bir yolu var mı? Bir istisna ortaya çıktığında ve yakalandığında Python önemli ölçüde yavaşlama eğilimindedir.
chiffa

1
@chiffa Bir tarih biçimi normal ifadesiyle eşleşebilirsiniz, ancak daha az sağlam olduğu ve istisnalar daha net olduğu için önerilmez. Tarih doğrulamanın darboğazınız olduğundan emin misiniz?
jamylak

1
Gerçekten değil, bu yüzden sonunda sadece bir fonksiyonda atma-dış yapı sararım. Ben sadece datetime kütüphanesinde Exception atmak tetikleyecek bool dönen bir doğrulama işlevi olduğunu şaşırttı.
chiffa

@chiffa Belki de bool dönen validating işlevini bilerek
içermediler

2
Tarihlerde sıfır dolgu isteyenler için, strptime sıfır dolgu konusunda katı olmadığı için bu çözüm çalışmaz. Boşluğunuzu soyduktan sonra kendi dizininizi uygulayın ya da sonuçtaki dizenin uzunluğunu kontrol edin ve sonra bu çözümü kullanın.
Suparshva

65

Pythondateutil kitaplığı (ve daha fazla) Bunun için tasarlanmıştır. Bunu datetimesizin için otomatik olarak bir nesneye dönüştürür ve ValueErroryapamazsa yükseltir .

Örnek olarak:

>>> from dateutil.parser import parse
>>> parse("2003-09-25")
datetime.datetime(2003, 9, 25, 0, 0)

Bu yükseltir ValueErrortarih biçimi doğru değil ise:

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

dateutilAyrıca, bilinen diğer biçimleri akıllıca işleyebildiğinden ve belirtimlerinizi değiştirmenize izin verdiğinden, gelecekte diğer biçimleri ayrıştırmaya ihtiyaç duyuyorsanız son derece kullanışlıdır: dateutilörnekleri ayrıştırma .

İhtiyacınız olursa zaman dilimlerini de işler.

Yorumlara dayalı güncelleme : parseayrıca, dayfirstbir tarih belirsizse gün veya ayın önce gelip gelmeyeceğini kontrol eden anahtar kelime argümanını da kabul eder . Bu varsayılan olarak Yanlış seçeneğidir. Örneğin

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

1
Çok fazla kabul edebilir, örneğin parse('13/12/2001')"13 Aralık" ama parse('11/12/2001')"12 Kasım" (ilk sonuç burada "11 Aralık" ı önerir).
jfs

2
parseaslında dayfirstbunu kontrol etmenizi sağlayan bir anahtar kelime argümanı alır . parse('11/12/2001', dayfirst=True)"11 Ara" dönecektir. dateutil'in varsayılan değeridayfirst=False
Jacinda

datetutil.parser.parse()çok fazla zaman biçimini kabul eden noktayı kaçırıyorsunuz (belirsiz girişe sahip başka örnekler bulabilirsiniz). Girişinizin YYYY-AA-GG biçiminde olduğunu doğrulamak istiyorsanız , parse()işlev yanlış araçtır.
jfs

1
Bu tamamen geçerli bir noktadır - eğer bu formatı gerçekten sınırlamak istiyorsanız, bunu yapmazsınız ve kabul edilen cevap zaten bu durumda doğru olanı yapmak için harika bir iş çıkarır. Cevabı yazdığımda, yazarın talep ettiği belirli formatın aksine geçerli bir tarih olup olmadığını nasıl doğrulayacağımı işaret eden satırlarda daha fazla düşündüğümü düşünüyorum, ki bu soru karşısında insanlar genellikle aramak.
Jacinda

Nesneye .parse()ek olarak biçim dizesini döndürmenin bir yolu var mı datetime?
citynorman

35

Bence tam validate fonksiyonu şöyle görünmeli:

from datetime import datetime

def validate(date_text):
    try:
        if date_text != datetime.strptime(date_text, "%Y-%m-%d").strftime('%Y-%m-%d'):
            raise ValueError
        return True
    except ValueError:
        return False

Sadece yürütmek

datetime.strptime(date_text, "%Y-%m-%d") 

strptime yöntemi ayın ve ayın sıfır basamaklı ondalık sayı olup olmadığını kontrol etmediği için yeterli değildir. Örneğin

datetime.strptime("2016-5-3", '%Y-%m-%d')

hatasız yürütülecektir.


3
"Teknik olarak haklısın - en iyi doğru tür." Bunu dizelerimde sağlamam gerekiyordu.
delrocco

Bu testlerime karşı iyi çalışıyor, ancak belgelerin belirttiği gibi yanlış görünüyor: "% d -> Ayın sıfır dolgulu ondalık sayı olarak -> 01, 02,…, 31" ve% m için aynı -> Ay, sıfır dolgulu ondalık sayı olarak. -> 01, 02,…, 12 docs.python.org/2/library/…
thanos.a

Ay ve günün sıfır dolgulu olduğunu kontrol etmeniz gerekiyorsa, yalnızca dizenin uzunluğunu kontrol etmek yeterli olmaz datetime.strptime(date_text, "%Y-%m-%d")mı?
Kyle Barron

17
from datetime import datetime

datetime.strptime(date_string, "%Y-%m-%d")

.. bu, ValueErroruyumsuz bir biçim alırsa a'yı yükseltir .

.. tarihler ve saatler ile çok uğraşıyorsanız (unix zaman damgası yüzerlerinin aksine tarih-saat nesneleri anlamında), pytz modülüne bakmak ve depolama / db için her şeyi UTC'de saklamak iyi bir fikirdir. .


2
Daha hýzlýydýn, bunu kendim gönderirdim ( ideone.com/vuxDDf ). Oyla.
Tadeck

.. yayınlandıktan hemen sonra gördüm ve bugün datetime nesneleriyle çalışıyorlardı.
Bay B

-7

Bu en kolay yol:

date = datetime.now()
date = date.strftime('%Y-%m-%d_%H-%M-%S.jpg')

2
Sadece kod yerine açıklama yapmak daha iyi olur.
lukas_o
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.