2013-06-01 59 views
63

Tôi có phương thức python chấp nhận đầu vào ngày làm chuỗi.Làm cách nào để xác thực định dạng chuỗi ngày trong python?

Làm cách nào để thêm xác thực để đảm bảo chuỗi ngày tháng được chuyển đến phương thức nằm trong ffg. định dạng:

'YYYY-MM-DD' 

nếu nó không phải là, phương pháp nên tăng một số loại lỗi

+2

Nó có thể là hơn Pythonic (xin tha thứ, không phải xin phép) không kiểm tra ở tất cả, và bắt bất kỳ trường hợp ngoại lệ kết quả xảy ra. – Thomas

+0

Liên quan: [Trong python, cách kiểm tra xem ngày có hợp lệ không?] (Http://stackoverflow.com/q/9987818/55075) – kenorb

Trả lời

101
>>> 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 
+0

Có cách nào để thực hiện điều đó mà không cần thử/ngoại trừ không? Python có xu hướng làm chậm đáng kể khi một ngoại lệ được nâng lên và bị bắt. – chiffa

+1

@chiffa Bạn có thể phù hợp với định dạng ngày tháng regex nhưng không được khuyến nghị vì nó ít mạnh mẽ hơn và ngoại lệ rõ ràng hơn. Bạn có chắc chắn ngày xác nhận là nút cổ chai của bạn? – jamylak

+0

Không thực sự, do đó, cuối cùng tôi sẽ chỉ ném ném-ngoại trừ xây dựng trong một chức năng. Tôi chỉ ngạc nhiên rằng không có hàm xác nhận bool-return nào có thể kích hoạt Exception throw trong thư viện datetime. – chiffa

34

Thư viện Python dateutil được thiết kế cho việc này (và nhiều hơn nữa). Nó sẽ tự động chuyển đổi điều này thành đối tượng datetime cho bạn và tăng ValueError nếu không thể.

Như một ví dụ:

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

Điều này đặt ra một ValueError nếu ngày không đúng định dạng:

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

dateutil cũng là cực kỳ hữu ích nếu bạn bắt đầu cần phải phân tích các định dạng khác trong tương lai , vì nó có thể xử lý hầu hết các định dạng đã biết một cách thông minh và cho phép bạn sửa đổi đặc điểm kỹ thuật của mình: dateutil parsing examples.

Nó cũng xử lý múi giờ nếu bạn cần.

Cập nhật dựa trên nhận xét: parse cũng chấp nhận đối số từ khóa dayfirst kiểm soát xem ngày hoặc tháng được dự kiến ​​đến trước nếu ngày không rõ ràng. Giá trị mặc định là False. Ví dụ.

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

nó có thể chấp nhận quá nhiều ví dụ:, "phân tích cú pháp ('13/12/2001')' là "ngày 13 tháng 12" nhưng "phân tích cú pháp ('11/12/2001 ')' là "ngày 12 tháng 11" (kết quả đầu tiên sẽ đề xuất "11 tháng 12" tại đây). – jfs

+0

'parse' thực sự lấy một đối số từ khóa' dayfirst' cho phép bạn kiểm soát điều này. 'phân tích cú pháp ('11/12/2001 ', dayfirst = True)' sẽ trả về "ngày 11 tháng 12" mặc định của dateutil là 'dayfirst = False' – Jacinda

+0

bạn đang thiếu điểm' datetutil.parser.parse() 'chấp nhận quá nhiều định dạng thời gian (bạn có thể tìm thấy các ví dụ khác với đầu vào mơ hồ). Nếu bạn muốn * xác thực * rằng đầu vào của bạn ở định dạng YYYY-MM-DD thì hàm 'parse()' là công cụ sai. – jfs

11
from datetime import datetime 

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

..this đặt ra một ValueError nếu nó nhận được một định dạng không tương thích.

.. nếu bạn đang xử lý ngày và giờ rất nhiều (theo ý nghĩa của đối tượng ngày giờ, trái ngược với dấu thời gian unix nổi), bạn nên xem mô-đun pytz và lưu trữ/db, lưu trữ mọi thứ trong UTC.

+2

Bạn đã nhanh hơn, tôi đã tự đăng nó (http://ideone.com/vuxDDf). Upvote. – Tadeck

+0

..chỉ thấy nó ngay sau khi nó được đăng, và xảy ra đã được làm việc với các đối tượng datetime ngày hôm nay. –

6

Tôi nghĩ rằng chức năng validate đầy đủ nên trông như thế này:

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 

Thi chỉ

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

là không đủ vì strptime phương pháp không kiểm tra trong tháng đó và ngày diễn ra tháng là số thập phân không đệm. Ví dụ:

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

sẽ được thực hiện mà không có lỗi.

+1

"Bạn đúng về mặt kỹ thuật - loại tốt nhất chính xác". Tôi cần phải đảm bảo điều này trong chuỗi của tôi. – delrocco

0

Đây là cách đơn giản nhất:

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

Định dạng ngày sai cho các câu hỏi –

Các vấn đề liên quan