Neden datetime.datetime.utcnow () saat dilimi bilgisi içermiyor?


285
datetime.datetime.utcnow()

Neden bu mu datetimeherhangi saat dilimi bilgisi açıkça bir UTC olduğu göz önüne alındığında değil datetime?

Bunun olmasını beklerdim tzinfo.


String türünde bir normal iso formatı tarih alanını utc formatına nasıl dönüştürebilirim?
Navi

Yanıtlar:


192

Bu, saat dilimi naif olduğu anlamına gelir, bu yüzden datetime.astimezone

böyle bir saat dilimi verebilirsin

import pytz  # 3rd party: $ pip install pytz

u = datetime.utcnow()
u = u.replace(tzinfo=pytz.utc) #NOTE: it works only with a fixed utc offset

şimdi zaman dilimlerini değiştirebilirsiniz

print(u.astimezone(pytz.timezone("America/New_York")))

Belirli bir saat diliminde geçerli saati almak için tzinfo'yu datetime.now()doğrudan şu adrese iletebilirsiniz :

#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz

print(datetime.now(pytz.timezone("America/New_York")))

Gün ışığından yararlanma saatini (DST) gözlemleyenler de dahil olmak üzere herhangi bir saat dilimi için çalışır, yani farklı zamanlarda farklı utc ofsetleri olabilen saat dilimleri için çalışır (sabit olmayan utc ofseti). Kullanmayın tz.localize(datetime.now())- yerel saat belirsiz olduğunda DST sonu geçişi sırasında başarısız olabilir.


216
Ancak saat dilimi naif olması için iyi bir neden yok - UTC olarak belirtildi. Düzgün çalışması için neden bir üçüncü taraf kitaplığı aramanız gerekiyor?
Mark Ransom

4
Katılıyorum; benim için 'naif' zamanlar tamamen işe yaramaz. Şu anda python listesinde stdlib'e pytz ekleme hakkında tartışma var; sorun lisanslama değil, saat dilimi verilerinin çok sık güncellenmesi (Python'un kendisi olamaz). Ayrıca pytz, tzinfo arayüzünü beklenen şekilde uygulamıyor, bu nedenle bazı şehir saat dilimlerini kullanmaya çalışırsanız hata alabilirsiniz astimezone. Bu nedenle datetime sadece yerel zaman dilimlerine sahip olmakla kalmaz, aynı zamanda tzinfo'nun yaygın olarak bulunan tek uygulaması söz konusu standarda uygun değildir.
bobince

5
@bobince Neden pytz ve standart datetime kütüphaneleri sizin için çalışmıyor? Python çekirdeği ve bağımsız projeler olarak gelişen pytz, çekirdek ekip için lojistik karmaşıklığı azaltır. Evet, Python çekirdek ekibinin karmaşıklığını azaltmak, zaman dilimleri ile uğraşması gereken tüm Python kullanıcıları için karmaşıklığı arttırıyor, ancak bu kararı iyi bir nedenden dolayı aldıklarına inanıyorum. "Standart kütüphanede tzinfo örneği yok ..." kuralı harika çünkü basit, neden burada bir istisna yapalım?
Derek Litz

15
Peki yau=datetime.now(pytz.utc)
Craig McQueen

4
@bain: kullanma tz.localize(datetime.now()); kullanın datetime.now(tz).
jfs

142

Python 3.2'den itibaren datetimemodülün içerdiğini unutmayın datetime.timezone. İçin belgeler datetime.utcnow()diyor:

Mevcut bir UTC tarih saatini arayarak elde edilebilir .datetime.now(timezone.utc)

Böylece şunları yapabilirsiniz:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2014, 7, 10, 2, 43, 55, 230107, tzinfo=datetime.timezone.utc)

2
Hangisi tercih edilir? datetime.now(timezone.utc)veya datetime.utcnow(timezone.utc)?
Jesse Webb

8
datetime.utcnow()hiçbir argüman almaz. Bu yüzden olmalı datetime.now(timezone.utc).
Craig McQueen

1
datetime.now()makine saatini datetime.utcnow()döndürür ancak gerçek UTC saatini döndürür.
Babu

13
@Babu: datetime.utcnow()set gelmez tzinfoo UTC olduğunu belirtmek için. Ancak set iledatetime.now(datetime.timezone.utc) UTC zamanını döndürür . tzinfo
Craig McQueen

@CraigMcQueen Şimdi yapıcıda bir tznesneyi iletirsek , o zaman diliminin zamanını döndürür? Tamam! İşaret ettiğiniz için teşekkürler.
Babu

71

Standart Python kütüphaneleri hiçbir tzinfo sınıfı içermez (ancak bkz. Pep 431 ). Sadece nedenlerini tahmin edebilirim. Şahsen, UTC'ye bir tzinfo sınıfı eklememenin bir hata olduğunu düşünüyorum, çünkü bu standart bir uygulamaya sahip olacak kadar tartışmasız.

Düzenleme: Kütüphanede uygulama olmamasına rağmen, tzinfodokümantasyonda örnek olarak verilen bir uygulama vardır .

from datetime import timedelta, tzinfo

ZERO = timedelta(0)

# A UTC class.

class UTC(tzinfo):
    """UTC"""

    def utcoffset(self, dt):
        return ZERO

    def tzname(self, dt):
        return "UTC"

    def dst(self, dt):
        return ZERO

utc = UTC()

Bunu kullanmak için, geçerli saati bilinçli bir datetime nesnesi olarak almak için:

from datetime import datetime 

now = datetime.now(utc)

Orada datetime.timezone.utc3.2+ Python:

from datetime import datetime, timezone 

now = datetime.now(timezone.utc)

8
Bu sınıfın neden ilk sırada verilmediğine (ve daha da önemlisi, datetimetarafından yaratılan nesneler için kullanıldığına utcnow()) göre şekil verin ...
André Caron

17
Zaman dilimi nesnesi timezone.utcnihayet Python 3.2'ye eklendi. Geriye dönük uyumluluk için utcnow()yine de saat dilimi olmayan bir zaman nesnesi döndürür, ancak istediğiniz şeyi elde ederek alabilirsiniz now(timezone.utc).
mhsmith

4
@rgove, bu Python 3 için adil bir oyun olması gereken hataların düzeltilmesi türündedir. Geriye dönük uyumluluktan endişelenmemelilerdi. Son birkaç gün içinde okuduğum başka bir örnek daha var - structmodül Unicode'dan sınamaya otomatik dönüşümler yapacaktı ve nihai karar, kötü bir kararın ilerlemesini önlemek için önceki Python 3 sürümleriyle uyumluluğu kırmaktı.
Mark Ransom

2
Python'un tzinfobelgelerinin onu uygulamak için kod örnekleri içerdiğinden şaşkına döndüm , ancak datetime'ın kendisinde bu işlevselliği içermiyorlar! docs.python.org/2/library/datetime.html#datetime.tzinfo.fromutc
LS

1
@LS evet, pytzharika bir kaynak. Örnek kod koymak için cevabımı düzenlediğimde, başka biri bunu önerdi ve gök gürültülerini çalmak istemedim.
Mark Ransom

20

pytzModül tek seçenektir ve başka yokturpython-dateutil rağmen üçüncü şahıs paketi de zaten diğer bağımlılıklar ve işletim sistemine bağlı olarak mevcut olabilen.

Ben sadece bu metodolojiyi referans olarak dahil etmek istedim. python-dateutilBaşka amaçlarla kurduysanız tzinfo, çoğaltmak yerinepytz

import datetime
import dateutil.tz

# Get the UTC time with datetime.now:
utcdt = datetime.datetime.now(dateutil.tz.tzutc())

# Get the UTC time with datetime.utcnow:
utcdt = datetime.datetime.utcnow()
utcdt = utcdt.replace(tzinfo=dateutil.tz.tzutc())

# For fun- get the local time
localdt = datetime.datetime.now(dateutil.tz.tzlocal())

Çağrıların utcnowUTC saat dilimi bilgilerini içermesi gerektiğini kabul ediyorum . Yerel datetime kitaplığı, çapraz uyumluluk için datIME varsayılan olarak ayarlandığından bunun dahil olmadığından şüpheleniyorum.


1
NameError: 'dt' adı tanımlanmadı
xApple

Datetime.datetime.utcfromtimestamp () çağrısını kullanıyordum ve tzinfo eklemeye ihtiyacım vardı, İkinci çözüm benim için çalıştı: utcdt = datetime.datetime.utcfromtimestamp(1234567890).replace(dateutil.tz.tzutc())
Ian Lee

1
not: aksine datetime.now(pytz_tz)her zaman çalışır; datetime.now(dateutil.tz.tzlocal())DST geçişleri sırasında başarısız olabilir . PEP 495 - Yerel Saat Belirsizliğidateutil gelecekte durumu iyileştirebilir .
jfs

@IanLee: Eğer kullanabilirsiniz utc_dt = datetime.fromtimestamp(1234567890, dateutil.tz.tzutc())(: not dateutilofset olmayan bir sabit UTC (gibi olan dateutil.tz.tzlocal()burada başarısız olabilir) , kullanmak bir pytzyerine tabanlı bir çözüm ).
jfs

Programım zaten içe aktarıldığı dateutiliçin dateutil.parserbu çözümü en çok sevdim. O kadar basit şekilde oluştu: utcCurrentTime = datetime.datetime.now(tz=dateutil.tz.tzutc()). Viyola!!
LS

11

Julien Danjou neden asla zaman dilimleri ile uğraşmamanız gerektiğini açıklayan iyi bir makale yazdı . Bir alıntı:

Aslında, Python datetime API her zaman habersiz datetime nesneleri döndürür, bu da çok talihsizdir. Gerçekten de, bu nesneden birini alır almaz, saat diliminin ne olduğunu bilmenin bir yolu yoktur, bu nedenle bu nesneler kendi başlarına oldukça "yararsızdır".

Ne yazık ki, kullanabilseniz bile utcnow(), keşfettiğiniz gibi saat dilimi bilgilerini göremezsiniz.

öneriler:

  • Daima bilinçli datetimenesneler kullanın , yani saat dilimi bilgisiyle. Bu, onları doğrudan karşılaştırabilmenizi sağlar (farkında ve farkında olmayan datetime nesneler karşılaştırılamaz) ve bunları kullanıcılara doğru bir şekilde döndürür. Kaldıraç pytz saat dilimi nesneleri olması.

  • Giriş ve çıkış dizesi biçimi olarak ISO 8601 kullanın . datetime.datetime.isoformat()Zaman damgalarını, saat dilimi bilgilerini içeren bu biçim kullanılarak biçimlendirilmiş dize olarak döndürmek için kullanın .

  • ISO 8601 biçimli zaman damgalarını içeren dizeleri ayrıştırmanız gerekirse, güvenebilirsiniz iso8601, bu da zaman dilimlerini doğru saat dilimi bilgileriyle döndürür. Bu, zaman damgalarını doğrudan karşılaştırılabilir hale getirir.


1
Bu biraz yanıltıcı bir öneridir. Temel kural, asla zaman dilimleri ile ilgilenmektir. Her zaman tz unware utc nesnelerini (epoch nesneleri) saklayın ve iletin. Saat dilimi sadece kullanıcı arabiriminde temsil anda hesaplanmalıdır
nehem

1
Bu zaten Julien'in düşüncelerine çok iyi uyuyor gibi görünüyor. Özel önerilerinden hangisi (yukarıda belirtildiği gibi) yanıltıcıdır?
Joe D'Andrea

10

timezonePython 3.2 ve üzeri sürümlere bilgi eklemek için

import datetime

>>> d = datetime.datetime.now(tz=datetime.timezone.utc)
>>> print(d.tzinfo)
'UTC+00:00'

1
AttributeError: 'module' object has no attribute 'timezone' Python 2.7.13 (varsayılan, 19 Oca 2017, 14:48:08)
Marcin Owsiany

-6
from datetime import datetime 
from dateutil.relativedelta import relativedelta
d = datetime.now()
date = datetime.isoformat(d).split('.')[0]
d_month = datetime.today() + relativedelta(months=1)
next_month = datetime.isoformat(d_month).split('.')[0]

-13

UTC tarihleri, UTC oldukları için herhangi bir saat dilimi bilgisine ihtiyaç duymaz;


10
Docs.python.org/library/datetime.html'den anlayabildiğim kadarıyla , tzinfo'su olmayan bir tarih saat diliminin belirtilmediği yerdir. Aşağıda saat dilimi vardır belirtildi, bu nedenle mantıksal olarak bunun mevcut olmalıdır. İlişkili bir saat dilimi olmayan bir tarih / saat ile kesinlikle UTC cinsinden bir tarih arasında büyük bir fark vardır. (İdeal olarak farklı IMO türleri olmalı, ama bu başka bir mesele ...)
Jon Skeet

@JonSkeet Sanırım Ignacio'nun UTC'nin bir saat dilimi olmadığı noktasını kaçırıyorsunuz. Bunu yazarken bu cevabın -9 puanı olması şaşırtıcı ...
CS

3
@CS: Ignacio asla bunu söylemedi ... ve kesinlikle konuşursak UTC bir zaman dilimi olmasa da, genellikle hayatları oldukça basitleştirmek için bir kişi olarak ele alınır (Python dahil, örneğin pytz.utc). UTC'den farkı bilinmeyen bir değer ile 0 olduğu bilinen bir değer arasında büyük bir fark olduğunu unutmayın. İkincisi, ne döndürmesi utcnow() gerektiğidir , IMO. Bu, dokümantasyon uyarınca "Yorumlamaya açık olmayan belirli bir anı temsil etmek için bilinçli bir nesne kullanılır" ile uyumludur.
Jon Skeet
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.