Định dạng ISO của đối tượng ngày giờ trong Python UTC không bao gồm Z (Zulu hoặc Zero offset)


120

Tại sao python 2.7 không bao gồm ký tự Z (Zulu hoặc độ lệch 0) ở cuối chuỗi isoformat của đối tượng datetime UTC không giống như JavaScript?

>>> datetime.datetime.utcnow().isoformat()
'2013-10-29T09:14:03.895210'

Trong khi đó trong javascript

>>>  console.log(new Date().toISOString()); 
2013-10-29T09:38:41.341Z

1
Giá trị ngày giờ trong Python KHÔNG có thông tin múi giờ. Hãy thử pytz hoặc Babel nếu bạn muốn thông tin múi giờ được lưu trong tem thời gian của mình.
tnknepp

67
datetime.datetime.utcnow().isoformat() + 'Z'
jfs


3
..và Z mất tích đáng ngạc nhiên gây ra một số điều không nên làm việc ví dụ như cuộc gọi API
thảo quả

Nó thậm chí còn tồi tệ hơn, nếu phần cuối cùng của datetime là 0, nó sẽ cắt bớt nó ...
ntg

Câu trả lời:


52

Các datetimeđối tượng Python không có thông tin múi giờ theo mặc định và nếu không có thông tin này, Python thực sự vi phạm đặc điểm kỹ thuật ISO 8601 ( nếu không có thông tin múi giờ nào được giả định là giờ địa phương ). Bạn có thể sử dụng gói pytz để lấy một số múi giờ mặc định hoặc trực tiếp phân lớp tzinfocho chính mình:

from datetime import datetime, tzinfo, timedelta
class simple_utc(tzinfo):
    def tzname(self,**kwargs):
        return "UTC"
    def utcoffset(self, dt):
        return timedelta(0)

Sau đó, bạn có thể thêm thông tin múi giờ theo cách thủ công vào utcnow():

>>> datetime.utcnow().replace(tzinfo=simple_utc()).isoformat()
'2014-05-16T22:51:53.015001+00:00'

Lưu ý rằng điều này KHÔNG phù hợp với định dạng ISO 8601, cho phép một trong hai Zhoặc +00:00làm hậu tố cho UTC. Lưu ý rằng cái sau thực sự tuân theo tiêu chuẩn tốt hơn, với cách các múi giờ được thể hiện nói chung (UTC là một trường hợp đặc biệt.)


108
làm thế nào để bao gồm Zthay vì +00:00?
leopoodle

14
CẢNH BÁO!!! pytzvi phạm tzinfogiao thức của Python và nguy hiểm khi sử dụng! Xem blog.ganssle.io/articles/2018/03/pytz-fastest-footgun.html
ivan_pozdeev

@ivan_pozdeev cảm ơn vì liên kết, rất thú vị. Lưu ý rằng các thay đổi cho phép dateutilhoạt động đã không được triển khai cho đến khi Python 3.6 với PEP 495, do đó, nói pytzkhông sử dụng giao diện tiêu chuẩn là không công bằng vì giao diện đã thay đổi. Trước khi thay đổi, cách duy nhất để làm cho nó hoạt động là cách pytzđã làm.
Mark Ransom vào

67

Lựa chọn: isoformat()

Python's datetimekhông hỗ trợ các hậu tố múi giờ quân sự như hậu tố 'Z' cho UTC. Thay thế chuỗi đơn giản sau đây thực hiện thủ thuật:

In [1]: import datetime

In [2]: d = datetime.datetime(2014, 12, 10, 12, 0, 0)

In [3]: str(d).replace('+00:00', 'Z')
Out[3]: '2014-12-10 12:00:00Z'

str(d) về cơ bản giống như d.isoformat(sep=' ')

Xem: Ngày giờ, Thư viện chuẩn Python

Lựa chọn: strftime()

Hoặc bạn có thể sử dụng strftimeđể đạt được hiệu quả tương tự:

In [4]: d.strftime('%Y-%m-%d %H:%M:%SZ')
Out[4]: '2014-12-10 12:00:00Z'

Lưu ý: Tùy chọn này chỉ hoạt động khi bạn biết ngày được chỉ định là UTC.

Xem: datetime.strftime ()


Bổ sung: Múi giờ có thể đọc được của con người

Đi xa hơn, bạn có thể quan tâm đến việc hiển thị thông tin múi giờ có thể đọc được của con người, pytzvới strftime %Zcờ múi giờ:

In [5]: import pytz

In [6]: d = datetime.datetime(2014, 12, 10, 12, 0, 0, tzinfo=pytz.utc)

In [7]: d
Out[7]: datetime.datetime(2014, 12, 10, 12, 0, tzinfo=<UTC>)

In [8]: d.strftime('%Y-%m-%d %H:%M:%S %Z')
Out[8]: '2014-12-10 12:00:00 UTC'

1
Dấu phân cách không phải là Tthay vì để trống?
Marcello Romani

1
nó phải d = datetime.datetime(2014, 12, 10, 12, 0, 0, tzinfo=datetime.timezone.utc)ở dòng 2. Btw., trong RFC3339 nó nói rằng một khoảng trắng là 'ok' (thay vì 'T').
MrFuppes

16

Các tập lệnh javascript và python sau đây cho kết quả giống hệt nhau. Tôi nghĩ đó là những gì bạn đang tìm kiếm.

JavaScript

new Date().toISOString()

Python

import datetime

datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'

Đầu ra mà họ đưa ra là thời gian utc (zelda) được định dạng dưới dạng chuỗi ISO với chữ số có nghĩa 3 mili giây và được nối với chữ Z.

2019-01-19T23:20:25.459Z

12

Trong Python> = 3.2, bạn chỉ cần sử dụng điều này:

>>> from datetime import datetime, timezone
>>> datetime.now(timezone.utc).isoformat()
'2019-03-14T07:55:36.979511+00:00'

3
Giải pháp rất hay. Đối với câu hỏi của họ về Z, bạn có thể cắt phần bù:.isoformat()[:-6] + 'Z'
Maximilian Burszley

11

Lịch ngày của Python hơi khó hiểu. Sử dụng arrow.

> str(arrow.utcnow())
'2014-05-17T01:18:47.944126+00:00'

Về cơ bản, Arrow có cùng api như datetime, nhưng có múi giờ và một số tiện ích bổ sung cần có trong thư viện chính.

Định dạng tương thích với Javascript có thể đạt được bằng cách:

arrow.utcnow().isoformat().replace("+00:00", "Z")
'2018-11-30T02:46:40.714281Z'

Javascript Date.parsesẽ lặng lẽ giảm micro giây từ dấu thời gian.


7
Điều này không trả lời câu hỏi vì chuỗi không kết thúc bằng 'Z'.
kaleissin

3

Có rất nhiều câu trả lời hay trên bài viết, nhưng tôi muốn định dạng xuất hiện chính xác như với JavaScript. Đây là những gì tôi đang sử dụng và nó hoạt động tốt.

In [1]: import datetime

In [1]: now = datetime.datetime.utcnow()

In [1]: now.strftime('%Y-%m-%dT%H:%M:%S') + now.strftime('.%f')[:4] + 'Z'
Out[3]: '2018-10-16T13:18:34.856Z'

3
pip install python-dateutil
>>> a = "2019-06-27T02:14:49.443814497Z"
>>> dateutil.parser.parse(a)
datetime.datetime(2019, 6, 27, 2, 14, 49, 443814, tzinfo=tzutc())

2

Tôi đã tiếp cận vấn đề này với một vài mục tiêu:

  • tạo chuỗi ngày giờ "nhận biết" UTC ở định dạng ISO 8601
  • chỉ sử dụng các hàm Thư viện chuẩn Python cho đối tượng datetime và tạo chuỗi
  • xác thực đối tượng datetime và chuỗi bằng timezonehàm tiện ích Django vàdateutil trình phân tích cú pháp
  • sử dụng các hàm JavaScript để xác thực rằng chuỗi ngày giờ ISO 8601 là UTC nhận biết

Cách tiếp cận này không bao gồm hậu tố Z và không sử dụng utcnow(), nhưng nó dựa trên khuyến nghị trong tài liệu Python và nó vượt qua tập hợp với Django và JavaScript.

Hãy bắt đầu bằng cách chuyển đối tượng múi giờ UTC datetime.now()thay vì sử dụng datetime.utcnow():

from datetime import datetime, timezone

datetime.now(timezone.utc)
>>> datetime.datetime(2020, 1, 8, 6, 6, 24, 260810, tzinfo=datetime.timezone.utc)

datetime.now(timezone.utc).isoformat()
>>> '2020-01-08T06:07:04.492045+00:00'

Điều đó có vẻ tốt, vì vậy hãy xem Django và dateutilnghĩ gì:

from django.utils.timezone import is_aware

is_aware(datetime.now(timezone.utc))
>>> True

import dateutil.parser

is_aware(dateutil.parser.parse(datetime.now(timezone.utc).isoformat()))
>>> True

Được rồi, đối tượng datetime trong Python và chuỗi ISO 8601 là "nhận biết" UTC. Bây giờ hãy xem JavaScript nghĩ gì về chuỗi ngày giờ. Mượn câu trả lời này, chúng tôi nhận được:

let date= '2020-01-08T06:07:04.492045+00:00';
const dateParsed = new Date(Date.parse(date))

document.write(dateParsed);
document.write("\n");
// Tue Jan 07 2020 22:07:04 GMT-0800 (Pacific Standard Time)

document.write(dateParsed.toISOString());
document.write("\n");
// 2020-01-08T06:07:04.492Z

document.write(dateParsed.toUTCString());
document.write("\n");
// Wed, 08 Jan 2020 06:07:04 GMT

Bạn cũng có thể muốn đọc bài đăng trên blog này .


1
Phần thưởng khi gắn bó với các chức năng thư viện cơ sở và theo dõi một bài đăng cũ hơn.
Victor Romeo

1

Bằng cách kết hợp tất cả các câu trả lời ở trên, tôi đã tạo ra hàm sau:

from datetime import datetime, tzinfo, timedelta
class simple_utc(tzinfo):
    def tzname(self,**kwargs):
        return "UTC"
    def utcoffset(self, dt):
        return timedelta(0)


def getdata(yy, mm, dd, h, m, s) :
    d = datetime(yy, mm, dd, h, m, s)
    d = d.replace(tzinfo=simple_utc()).isoformat()
    d = str(d).replace('+00:00', 'Z')
    return d


print getdata(2018, 02, 03, 15, 0, 14)

1

Tôi sử dụng con lắc:

import pendulum


d = pendulum.now("UTC").to_iso8601_string()
print(d)

>>> 2019-10-30T00:11:21.818265Z

0
>>> import arrow

>>> now = arrow.utcnow().format('YYYY-MM-DDTHH:mm:ss.SSS')
>>> now
'2018-11-28T21:34:59.235'
>>> zulu = "{}Z".format(now)
>>> zulu
'2018-11-28T21:34:59.235Z'

Hoặc, để có được nó trong một lần rơi sà xuống:

>>> zulu = "{}Z".format(arrow.utcnow().format('YYYY-MM-DDTHH:mm:ss.SSS'))
>>> zulu
'2018-11-28T21:54:49.639Z'
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.