Python UTC datetime nesnesinin ISO biçimi Z (Zulu veya Sıfır ofset) içermez


120

Python 2.7, JavaScript'in aksine UTC datetime nesnesinin izoformat dizesinin sonunda neden Z karakterini (Zulu veya sıfır ofseti) içermiyor?

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

Javascript'te ise

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

1
Python tarih saat değerlerinin saat dilimi bilgisi YOKTUR. Saat damganızda saat dilimi bilgilerinin saklanmasını istiyorsanız pytz veya Babel'i deneyin.
tnknepp

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


3
.. ve eksik Z şaşırtıcı bir şekilde bazı şeylerin çalışmamasına neden oluyor, örneğin API çağrısı
cardamom

Daha da kötüye gidiyor, eğer tarih
saatinin

Yanıtlar:


52

Python datetimenesneleri varsayılan olarak saat dilimi bilgisine sahip değildir ve bu olmadan Python aslında ISO 8601 spesifikasyonunu ihlal eder ( saat dilimi bilgisi verilmemişse, yerel saat olduğu varsayılır ). Bazı varsayılan saat dilimlerini elde etmek için pytz paketini kullanabilir veya doğrudan tzinfokendiniz alt sınıflara ayırabilirsiniz :

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

Ardından, saat dilimi bilgilerini manuel olarak şuraya ekleyebilirsiniz utcnow():

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

Bunun, UTC'nin son ekine Zveya +00:00son ekine izin veren ISO 8601 biçimine uygun OLDUĞUNU unutmayın . İkincisinin, saat dilimlerinin genel olarak nasıl temsil edildiği ile aslında standarda daha iyi uyduğunu unutmayın (UTC özel bir durumdur.)


108
Zyerine nasıl dahil ederim +00:00?
leopoodle

14
UYARI!!! pytzPython'un tzinfoprotokolünü ihlal eder ve kullanımı tehlikelidir! Bkz. Blog.ganssle.io/articles/2018/03/pytz-fastest-footgun.html
ivan_pozdeev

@ivan_pozdeev bağlantı için teşekkürler, çok ilginç. dateutilÇalışmaya izin veren değişikliklerin PEP 495 ile Python 3.6'ya kadar uygulanmadığını unutmayın, bu yüzden pytzstandart arayüzü kullanmadım, çünkü arayüz değişti. Değişimden önce, onu çalıştırmanın tek yolu, bunu yapmaktı pytz.
Mark Ransom

67

Seçenek: isoformat()

Python , UTC için 'Z' eki gibi askeri zaman dilimi eklerini datetimedesteklemiyor . Aşağıdaki basit dize değişimi hile yapar:

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) esasen aynıdır d.isoformat(sep=' ')

Görmek: Datetime, Python Standart Kitaplığı

Seçenek: strftime()

Veya strftimeaynı etkiyi elde etmek için kullanabilirsiniz :

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

Not: Bu seçenek yalnızca belirtilen tarihin UTC olarak olduğunu bildiğinizde çalışır.

Bakınız: datetime.strftime ()


Ek: İnsan Okuyabilir Saat Dilimi

Daha da ileri giderek, saat dilimi bayrağıyla pytzbirlikte insanlar tarafından okunabilir saat dilimi bilgilerini görüntülemek ilginizi çekebilir strftime %Z:

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
Ayırıcının Tboş olması gerekmez mi?
Marcello Romani

1
d = datetime.datetime(2014, 12, 10, 12, 0, 0, tzinfo=datetime.timezone.utc)2. satırda olmalıdır . Btw., RFC3339'da bir boşluğun 'tamam' olduğunu söyler ('T' yerine).
MrFuppes

16

Aşağıdaki javascript ve python betikleri aynı çıktıları verir. Sanırım aradığınız şey bu.

JavaScript

new Date().toISOString()

piton

import datetime

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

Verdikleri çıktı, 3 milisaniye anlamlı basamaklı ve Z ile eklenen bir ISO dizesi olarak biçimlendirilmiş utc (zelda) zamanıdır.

2019-01-19T23:20:25.459Z

12

Python> = 3.2'de şunu kullanabilirsiniz:

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

3
Çok güzel çözüm. Z.isoformat()[:-6] + 'Z'
İle

11

Python veri zamanları biraz hantal. Kullanın arrow.

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

Arrow, esasen datetime ile aynı API'ye sahiptir, ancak saat dilimleri ve ana kitaplıkta olması gereken bazı ekstra niteliklere sahiptir.

Javascript ile uyumlu bir format şu şekilde elde edilebilir:

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

Javascript Date.parse, zaman damgasından mikrosaniyeleri sessizce bırakacaktır.


7
Dize 'Z' ile bitmediği için bu soruya cevap vermez.
kaleissin

3

Gönderide pek çok iyi cevap var, ancak formatın aynen JavaScript'te olduğu gibi çıkmasını istedim. Kullandığım şey bu ve iyi çalışıyor.

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

3

Bu soruna birkaç hedefle yaklaştım:

  • ISO 8601 biçiminde bir UTC "farkında" tarih saat dizesi oluştur
  • datetime nesnesi ve dize oluşturma için yalnızca Python Standart Kitaplık işlevlerini kullanın
  • datetime nesnesini ve dizesini bir Django timezoneyardımcı program işlevi ve dateutilayrıştırıcıyla doğrulayın
  • ISO 8601 tarih saat dizesinin UTC farkında olduğunu doğrulamak için JavaScript işlevlerini kullanın

Bu yaklaşım değildir Z eki içerir ve gelmez kullanmak utcnow(), ancak dayanıyor Python belgelerinde öneri ve Django ve JavaScript ile toplayabilecek geçer.

datetime.now()Kullanmak yerine bir UTC saat dilimi nesnesi geçirerek başlayalım 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'

Bu iyi görünüyor , hadi Django'nun ne dateutilolduğunu görelim ve düşünelim :

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

Tamam, Python tarih saat nesnesi ve ISO 8601 dizesi UTC "farkındadır". Şimdi JavaScript'in datetime dizesi hakkında ne düşündüğüne bakalım. Bu cevaptan ödünç alırız:

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

Bu blog yazısını da okumak isteyebilirsiniz .


1
Temel kütüphane işlevlerine bağlı kalma ve eski bir gönderiyi takip etme bonusu.
Victor Romeo

1

Yukarıdaki tüm cevapları birleştirerek aşağıdaki işlevi elde ettim:

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

Sarkaç kullanıyorum:

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'

Veya bir çırpıda elde etmek için:

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