Phân tích cú pháp các dấu thời gian có đệm khác 0 bằng Python


83

Tôi muốn lấy lịch ngày từ các dấu thời gian như sau: 3/1/2014 9:55with datetime.strptime, hoặc cái gì đó tương đương.

Tháng, ngày trong tháng và giờ không được đệm bằng 0, nhưng dường như không có chỉ thị định dạng nào được liệt kê ở đây có thể tự động phân tích cú pháp này.

Cách tốt nhất để làm như vậy là gì? Cảm ơn!

Câu trả lời:


130

strptimecó thể phân tích cú pháp các giá trị không đệm. Thực tế là chúng được ghi nhận là được đệm trong bảng mã định dạng áp dụng cho strftimeđầu ra của. Vì vậy, bạn chỉ có thể sử dụng

datetime.strptime(datestr, "%m/%d/%Y %H:%M")

8

strptimekhông yêu cầu các giá trị có đệm 0. Xem ví dụ bên dưới

datetime.strptime("3/1/2014 9:55", "%m/%d/%Y %H:%M")
output:   datetime.datetime(2014, 3, 1, 9, 55)

2

Chỉ trong trường hợp câu trả lời này giúp ích cho người khác - tôi đến đây nghĩ rằng tôi đã gặp vấn đề với không đệm, nhưng thực tế là liên quan đến 12:00 so với 00:00 và bộ %Iđịnh dạng.

Bộ %Iđịnh dạng có nghĩa là phù hợp với 12 giờ đồng hồ, tùy chọn không đệm. Nhưng tùy thuộc vào nguồn dữ liệu của bạn, bạn có thể nhận được dữ liệu cho biết rằng nửa đêm hoặc giữa trưa thực sự bằng 0, ví dụ:

>>> datetime.strptime('2015/01/01 0:12am', "%Y/%m/%d %I:%M%p")
ValueError: time data '2015/01/01 0:12am' does not match format '%Y/%m/%d %I:%M'

Điều strptimethực sự muốn là số 12, không phải số 0:

>>> datetime.strptime('2015/01/01 12:12am', "%Y/%m/%d %I:%M%p")
datetime.datetime(2015, 1, 1, 0, 12)

Nhưng không phải lúc nào chúng ta cũng kiểm soát được nguồn dữ liệu của mình! Giải pháp của tôi cho trường hợp cạnh này là bắt ngoại lệ, thử phân tích cú pháp nó bằng a %H, kiểm tra nhanh xem chúng tôi đang ở trong trường hợp cạnh mà chúng tôi nghĩ rằng chúng tôi đang ở trong đó.

def get_datetime(string):
    try:
        timestamp = datetime.strptime(string, "%m/%d/%Y %I:%M%p")
    except ValueError:
        # someone used zero for midnight?
        timestamp = datetime.strptime(string, "%m/%d/%Y %H:%M%p")
        assert string.lower().endswith('am')
        assert timestamp.hour == 0
    return timestamp

0:12amlà đầu vào không hợp lệ. Nó nên được 12:12am. 11:59 pmđược theo sau bởi 12:00 am, không 0:00am. Có thể có nhiều cách để cung cấp dữ liệu sai định dạng thời gian, ví dụ: đầu vào có thể sử dụng năm ( %y) hai chữ số thay vì năm bốn chữ số ( %Y) hoặc ngày / tháng có thể được hoán đổi ( %m/%dso với %d/%m), v.v. Ngày / trường hợp tháng có thể không rõ ràng, ví dụ, 2015/10/12đó là "ngày 12 tháng 10" hay "ngày 10 tháng 12"? btw, bạn nên sử dụng %Y/%m/%dthay vì %m/%d/%Yđể khớp với định dạng đầu vào của bạn.
jfs

Cảm ơn, tôi nhận ra đó là đầu vào không hợp lệ, như tôi đã nói, nó đến từ nguồn dữ liệu mà tôi không kiểm soát.
hwjp

1

Cách không theo khuôn mẫu là sử dụng dateutil.parsemô-đun, nó cho phép phân tích cú pháp các định dạng ngày phổ biến, ngay cả khi bạn không biết nó đang sử dụng gì hiện tại
Ví dụ:

>>> import dateutil.parser
>>> 
>>> utc_time     = '2014-08-13T00:00:00'
>>> verbose_time = '13-Aug-2014'
>>> some_locale  = '3/1/2014 9:55'
>>> dateutil.parser.parse(utc_time)
datetime.datetime(2014, 8, 13, 0, 0)
>>> dateutil.parser.parse(verbose_time)
datetime.datetime(2014, 8, 13, 0, 0)
>>> dateutil.parser.parse(some_locale)
datetime.datetime(2014, 3, 1, 9, 55)

1

Bạn có thể xem tài liệu strftime tại đây, nhưng trên thực tế chúng không hoạt động tốt trên tất cả các nền tảng , ví dụ: ,%-d,%-mkhông hoạt động trên win7 bằng python 2.7 , nên bạn có thể hoàn thành như thế này

>>> date_str = '{d.year}-{d.month}-{d.day}'.format(d=datetime.datetime.now())  
>>> print(date_str)
2016-5-23

1
Trong Windows gốc, hàm băm được thay thế cho dấu gạch ngang: %#d, %#m. Nhưng cả mod dấu gạch ngang và mod băm chỉ cần thiết trong định dạng chuỗi ( strftime), không cần thiết trong phân tích cú pháp ( strptime).
Nuno André
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.