Làm thế nào để chuyển đổi chuỗi nhận biết múi giờ thành datetime trong Python mà không cần dateutil?


80

Tôi phải chuyển đổi một chuỗi nhận biết múi giờ như "2012-11-01T04:16:13-04:00"một datetimeđối tượng Python .

Tôi đã thấy dateutilmô-đun có chức năng phân tích cú pháp, nhưng tôi không thực sự muốn sử dụng nó vì nó thêm phụ thuộc.

Vậy tôi có thể làm như thế nào? Tôi đã thử một cái gì đó như sau, nhưng không may mắn.

datetime.datetime.strptime("2012-11-01T04:16:13-04:00", "%Y-%m-%dT%H:%M:%S%Z")

2
Có gì sai khi thêm một phụ thuộc khi phụ thuộc đó đáp ứng chính xác các yêu cầu của bạn? Chắc chắn nếu có thể đạt được kết quả tương tự mà không có mô-đun bổ sung, thì sẽ không có lý do gì để mô-đun tồn tại cả, phải không? Bạn thấy khó khăn như thế nào để thêm một người phụ thuộc?
Jon Skeet

Tôi nghĩ đó có thể là một đặc ân cá nhân? Tôi không thực sự muốn giới thiệu toàn bộ một mô-đun lớn vào dự án vì tôi chỉ cần một chức năng nhỏ.
lxyu

2
Gì vậy chi phí cụ thể của việc thêm một phụ thuộc vào dự án của bạn, so với chi phí làm mã của bạn khó khăn hơn để hiểu hơn nó cần phải được. Bỏ qua thực tế rằng bạn hiện chỉ cần một chức năng duy nhất - tập trung vào chi phí.
Jon Skeet

Câu trả lời:


92

Kể từ Python 3.7, datetime.datetime.fromisoformat()có thể xử lý định dạng của bạn:

>>> import datetime
>>> datetime.datetime.fromisoformat('2012-11-01T04:16:13-04:00')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000)))

Trong các phiên bản Python cũ hơn, bạn không thể, không phải không có toàn bộ quá trình xác định múi giờ thủ công.

Python không bao gồm cơ sở dữ liệu múi giờ, vì nó sẽ lỗi thời quá nhanh. Thay vào đó, Python dựa vào các thư viện bên ngoài, có thể có chu kỳ phát hành nhanh hơn nhiều, để cung cấp múi giờ được định cấu hình đúng cho bạn.

Như một tác dụng phụ, điều này có nghĩa là phân tích cú pháp múi giờ cũng cần phải là một thư viện bên ngoài. Nếu dateutilquá nặng đối với bạn, hãy sử dụng iso8601thay thế, nó sẽ phân tích cú pháp định dạng cụ thể của bạn rất tốt:

>>> import iso8601
>>> iso8601.parse_date('2012-11-01T04:16:13-04:00')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=<FixedOffset '-04:00'>)

iso8601là một 4KB nhỏ khổng lồ . So sánh python-dateutiltổng 148KB của tổng.

Kể từ Python 3.2, Python có thể xử lý các múi giờ dựa trên bù đắp đơn giản và %zsẽ phân tích cú pháp -hhmm+hhmmchênh lệch múi giờ trong một dấu thời gian. Điều đó có nghĩa là đối với dấu thời gian ISO 8601, bạn phải xóa dấu thời gian :trong múi giờ:

>>> from datetime import datetime
>>> iso_ts = '2012-11-01T04:16:13-04:00'
>>> datetime.strptime(''.join(iso_ts.rsplit(':', 1)), '%Y-%m-%dT%H:%M:%S%z')
datetime.datetime(2012, 11, 1, 4, 16, 13, tzinfo=datetime.timezone(datetime.timedelta(-1, 72000)))

Việc thiếu phân tích cú pháp ISO 8601 thích hợp đang được theo dõi trong vấn đề Python 15873 .


Đối với tôi, dường như datetimecó thể bao gồm một cái gì đó như iso8601để xử lý các múi giờ ISO 8601 - một chút phân tích cú pháp và hai tzinfolớp con.
Eryk Sun

@eryksun: ISO8601 thực sự đơn giản về múi giờ, nhưng một khi bạn bao gồm những khoảng lệch đó trong python stdlib, bạn sẽ bị ngập trong những hiểu lầm về lý do tại sao múi giờ trong đời thực (không chỉ là một khoảng lệch) không hoạt động, v.v.
Martijn Pieters

1
nó không phải là quá đau để xác định một FixedOffset lớp. Đây là ví dụ về mã
jfs

47

Đây là Tài liệu Python cho đối tượng datetime sử dụng gói dateutil ..

from dateutil.parser import parse

get_date_obj = parse("2012-11-01T04:16:13-04:00")
print get_date_obj

5
Đây được coi là câu trả lời đúng để làm điều này mà không cần lib bên ngoài
Paullo

6
@Paullo python-dateutil chính xác là "bên ngoài lib".
The Godfather

Câu trả lời hàng đầu không phù hợp với tôi với chữ 'Z' ở cuối, nhưng câu trả lời này đã làm được.
user1503941

13

Có hai vấn đề với mã trong câu hỏi ban đầu: không được có một :múi giờ trong múi giờ và chuỗi định dạng cho "múi giờ làm điểm bù" là chữ thường %zchứ không phải chữ hoa %Z.

Điều này phù hợp với tôi trong Python v3.6

>>> from datetime import datetime
>>> t = datetime.strptime("2012-11-01T04:16:13-0400", "%Y-%m-%dT%H:%M:%S%z")
>>> print(t)
2012-11-01 04:16:13-04:00

Khi nó sai, tại sao lại print(t)thêm dấu hai chấm vào phần bù utc?
moooeeeep

@moooeeeep Vì theo mặc định, datetime sử dụng hàm isoformat(sep=' ')for __str__sẽ in độ lệch UTC là "+ HH: MM". Sử dụng print(t.strftime("%Y-%m-%dT%H:%M:%S%z"))sẽ in không có ":" trong múi giờ.
Jamie Czuy

3
Có dấu hai chấm trong múi giờ không sai. Nhiều nguồn tin trình bày lần họ ở dạng chuỗi: 2012-11-01T04:16:13-04:00. OP đang tìm cách phân tích cú pháp biểu mẫu đó.
DaveL17

2

Bạn có thể chuyển đổi như thế này.

date = datetime.datetime.strptime('2019-3-16T5-49-52-595Z','%Y-%m-%dT%H-%M-%S-%f%z')
date_time = date.strftime('%Y-%m-%dT%H:%M:%S.%fZ')

1

Tôi mới làm quen với Python, nhưng đã tìm thấy một cách để chuyển đổi

2017-05-27T07:20:18.000-04:00 đến

2017-05-27T07:20:18 mà không cần tải xuống các tiện ích mới.

from datetime import datetime, timedelta

time_zone1 = int("2017-05-27T07:20:18.000-04:00"[-6:][:3])
>>returns -04

item_date = datetime.strptime("2017-05-27T07:20:18.000-04:00".replace(".000", "")[:-6], "%Y-%m-%dT%H:%M:%S") + timedelta(hours=-time_zone1)

Tôi chắc rằng có nhiều cách tốt hơn để làm điều này mà không cần cắt chuỗi quá nhiều, nhưng điều này đã hoàn thành công việc.

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.