Yerel saat dizesini UTC'ye nasıl dönüştürebilirim?


307

Nasıl bir tarih saat dönüştürebilirim yerel saatte dize a UTC zamanı dize ?

Eminim bunu daha önce yaptım, ama bulamıyorum ve SO umarım gelecekte bana (ve diğerlerine) yardımcı olacaktır.

Açıklama : Ben Örneğin, 2008-09-17 14:02:00benim yerel saat diliminde (içinde +10), ben eşdeğer olan bir dize oluşturmak istiyorum UTCzaman: 2008-09-17 04:02:00.

Ayrıca, http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/ adresinden , genel olarak bunun DST ve diğer konularda olduğu gibi yerel saatten UTC zamanı.


1
Mktime () yönteminin girdi olarak beklediğiniz gibi olmayabileceği bir "yerel zaman" aldığını unutmayın, onu kullandım ve her şeyi berbat etti. Lütfen bu bağlantıya
Haifeng Zhang

Yanıtlar:


287

İlk olarak, dizeyi naif bir datetime nesnesine ayrıştırın. Bu, datetime.datetimeiliştirilmiş saat dilimi bilgisi olmayan bir örnektir . datetime.strptimeTarih dizesini ayrıştırma hakkında bilgi için belgelere bakın .

pytzSaat dilimlerinin tam listesi + UTC ile birlikte gelen modülü kullanın . Yerel saat diliminin ne olduğunu belirleyin, ondan bir saat dilimi nesnesi oluşturun ve onu değiştirip saf tarih saatine ekleyin.

Son olarak, datetime.astimezone()tarih saatini UTC'ye dönüştürmek için yöntemi kullanın.

"2001-2-3 10:11:12" dizesi için yerel saat dilimi "America / Los_Angeles" kullanarak kaynak kodu:

import pytz, datetime
local = pytz.timezone ("America/Los_Angeles")
naive = datetime.datetime.strptime ("2001-2-3 10:11:12", "%Y-%m-%d %H:%M:%S")
local_dt = local.localize(naive, is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc)

Oradan strftime(), UTC tarih saatini gerektiği gibi biçimlendirmek için yöntemi kullanabilirsiniz :

utc_dt.strftime ("%Y-%m-%d %H:%M:%S")

7
Lütfen cevabınızı aşağıdaki kodla düzenleyin: [code] local.localize (naive) [/ code] Belgeye bakın: bağlantı Maalesef birçok zaman dilimi için pytz ile standart datetime kurucularının '' çalışmıyor '' argümanını kullanmak. >>> datetime (2002, 10, 27, 12, 0, 0, tzinfo = amsterdam) .strftime (fmt) '2002-10-27 12:00:00 AMT + 0020'
Sam Stoelinga

2
Görünüşe göre "yerel saat diliminin ne olduğunu anlayın" adımı, göründüğünden daha zor olduğunu gösteriyor (neredeyse imkansız).
Jason R. Coombs

2
@SamStoelinga tarafından önerildiği gibi local.localize öğesini kullanın, aksi takdirde yaz saati uygulamasını dikkate almayacaksınız.
Emil Stenström

Bu cevap bana çok yardımcı oldu, ancak karşılaştığım bir tuzağa işaret etmek istiyorum. Saati belirtirseniz, tarih vermezseniz, beklenmedik sonuçlar alabilirsiniz. Bu yüzden tam bir zaman damgası sağladığınızdan emin olun.
Steven Mercatante


145

Datetime modülünün utcnow () işlevi geçerli UTC saatini elde etmek için kullanılabilir.

>>> import datetime
>>> utc_datetime = datetime.datetime.utcnow()
>>> utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2010-02-01 06:59:19'

Tom'un yukarıda bahsettiği bağlantıdan: http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/ diyor ki:

UTC, gün ışığından yararlanma saati olmayan bir zaman dilimi ve geçmişte yapılandırma değişiklikleri olmayan bir saat dilimi.

Saati her zaman UTC olarak ölçün ve saklayın .

Zamanın nerede kaydedildiğini kaydetmeniz gerekiyorsa, ayrı olarak saklayın. Etmeyin yerel saat + saat dilimi bilgilerini saklamak!

NOT - Verilerinizden herhangi biri DST kullanan bir bölgedeyse pytz, John Millikin'in yanıtını kullanın ve bir göz atın.

Belirli bir dizeden UTC saatini almak ve dünyada DST kullanmayan bir bölgede olmak için yeterince şanslıysanız veya DST uygulanmadığında yalnızca UTC'den dengelenen verileriniz varsa:

-> ofset değerinin temeli olarak yerel saati kullanmak:

>>> # Obtain the UTC Offset for the current system:
>>> UTC_OFFSET_TIMEDELTA = datetime.datetime.utcnow() - datetime.datetime.now()
>>> local_datetime = datetime.datetime.strptime("2008-09-17 14:04:00", "%Y-%m-%d %H:%M:%S")
>>> result_utc_datetime = local_datetime + UTC_OFFSET_TIMEDELTA
>>> result_utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2008-09-17 04:04:00'

-> Veya bilinen bir ofsetten datetime.timedelta () kullanarak:

>>> UTC_OFFSET = 10
>>> result_utc_datetime = local_datetime - datetime.timedelta(hours=UTC_OFFSET)
>>> result_utc_datetime.strftime("%Y-%m-%d %H:%M:%S")
'2008-09-17 04:04:00'

GÜNCELLEME:

Python 3.2 datetime.timezonemevcut olduğundan. Aşağıdaki komutla bir saat dilimine duyarlı datetime nesnesi oluşturabilirsiniz:

import datetime

timezone_aware_dt = datetime.datetime.now(datetime.timezone.utc)

Saat dilimi dönüşümlerini yapmaya hazırsanız şunu okuyun:

https://medium.com/@eleroy/10-things-you-need-to-know-about-date-and-time-in-python-with-datetime-pytz-dateutil-timedelta-309bfbafb3f7


14
Bu sadece şimdiki zaman dönüştürür, herhangi bir zaman (bir dize olarak) almak ve UTC dönüştürmek gerekir.
Tom

Standart ofset değerlerini kullanıyorsanız, burada önemli olması gerektiğini düşünmüyorum. local_time = utc_time + utc_offset VE utc_time = local_time - utc_offset.
monkut

5
Geçmiş ve gelecek zaman damgalarının DST nedeniyle farklı UTC dengelemeleri olabileceğinden yalnızca geçerli saatle çalışır.
Alex B

iyi bir nokta ... DST ile uğraşmak zorunda kalırsanız muhtemelen John Millikin tarafından belirtildiği gibi pytz kullanıyor olmalısınız.
monkut

1
Utcnow () ve now () çağrıları arasında ara sıra bir delta vardır. Bu, daha sonra benzeri garip hatalara yol açabilecek tehlikeli bir kod satırıdır tzinfo.utcoffset() must return a whole number of minutes.
Pavel Vlasov

62

Teşekkürler @rofly, dizeden dizeye tam dönüşüm aşağıdaki gibidir:

time.strftime("%Y-%m-%d %H:%M:%S", 
              time.gmtime(time.mktime(time.strptime("2008-09-17 14:04:00", 
                                                    "%Y-%m-%d %H:%M:%S"))))

time/ calendarFonksiyonları özeti :

time.strptime
string -> tuple (saat dilimi uygulanmadığından dize ile eşleşir)

time.mktime
yerel zaman grubu - çağdan beri saniye (her zaman yerel saat)

time.gmtime
dönemden bu yana saniyeler -> UTC'de tuple

ve

calendar.timegm
UTC'de tuple -> çağdan beri saniye

time.localtime
dönemden bu yana saniye -> yerel saat diliminde


4
(always local time)yanlış görünüyor: mktime () girdisi yerel saattir, çıkış 1970-01-01 00:00:00 +0000 (UTC)saat dilimine bağlı olmayan epoch ( ) 'den beri saniyelerdir .
jfs

3
Ayrıca DST geçişi sırasında başarısız olma şansı% 50'dir. Bkz LOCALTIME ile ilgili sorunlar
jfs

38

İşte yaygın Python zaman dönüşümlerinin bir özeti.

Bazı yöntemler saniye kesirlerini düşürür ve (s) ile işaretlenmiştir . Bunun yerine açık bir formül ts = (d - epoch) / unitkullanılabilir (teşekkürler jfs).

  • struct_time (UTC) → POSIX (ler) :
    calendar.timegm(struct_time)
  • Naif tarih (yerel) → POSIX (s) :
    calendar.timegm(stz.localize(dt, is_dst=None).utctimetuple())
    (DST geçişleri sırasında istisna, jfs'den yoruma bakın)
  • Naif tarih (UTC) → POSIX (s) :
    calendar.timegm(dt.utctimetuple())
  • Farkında tarih → → POSIX (ler) :
    calendar.timegm(dt.utctimetuple())
  • POSIX → struct_time (UTC, sn ):
    time.gmtime(t)
    ( jfs'den yoruma bakınız)
  • Naif tarih (yerel) → struct_time (UTC, s ):
    stz.localize(dt, is_dst=None).utctimetuple()
    (DST geçişleri sırasında istisna , jfs'den yoruma bakın)
  • Naif tarih (UTC) → struct_time (UTC, s ):
    dt.utctimetuple()
  • Farkında tarih / saat → struct_time (UTC, sn ):
    dt.utctimetuple()
  • POSIX → Normal tarih (yerel):
    datetime.fromtimestamp(t, None)
    (belirli koşullarda başarısız olabilir, aşağıdaki jfs'den yoruma bakın)
  • struct_time (UTC) → Naïve datetime (yerel, s ):
    datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz).replace(tzinfo=None)
    (artık saniye sayısını temsil edemez , jfs'nin yorumuna bakın)
  • Naif datetime (UTC) → Naif datetime (yerel):
    dt.replace(tzinfo=UTC).astimezone(tz).replace(tzinfo=None)
  • Farkında tarih → → Naif tarih (yerel):
    dt.astimezone(tz).replace(tzinfo=None)
  • POSIX → Normal tarih (UTC):
    datetime.utcfromtimestamp(t)
  • struct_time (UTC) → Naïve datetime (UTC, s ):
    datetime.datetime(*struct_time[:6])
    (artık saniye sayısını temsil edemez , jfs'nin yorumuna bakın)
  • Naïve datetime (yerel) → Naïve datetime (UTC):
    stz.localize(dt, is_dst=None).astimezone(UTC).replace(tzinfo=None)
    (DST geçişleri sırasında istisna, jfs'den yoruma bakın)
  • Farkında tarih → → Naif tarih (UTC):
    dt.astimezone(UTC).replace(tzinfo=None)
  • POSIX → Farkında tarih:
    datetime.fromtimestamp(t, tz)
    (pytz dışı zaman dilimleri için başarısız olabilir)
  • struct_time (UTC) → Farkında tarih (ler) :
    datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz)
    (artık saniye sayısını temsil edemez, jfs'nin yorumuna bakın)
  • Naif tarih (yerel) → Bilinen tarih:
    stz.localize(dt, is_dst=None)
    (DST geçişleri sırasında istisna, jfs'den yoruma bakın)
  • Naif tarih (UTC) → Bilinen tarih:
    dt.replace(tzinfo=UTC)

Kaynak: taaviburns.ca


1
(1) fromtimestamp(t, None)yerel saat diliminin adresinde farklı utc uzaklığı varsa t ve C kitaplığının belirtilen platformdaki tz veritabanına erişimi yoksa başarısız olabilir . tzlocal.get_localzone()Taşınabilir bir şekilde tzdata sağlamak için kullanabilirsiniz . (2) fromtimestamp(t, tz)pytz olmayan zaman dilimleri için başarısız olabilir. (3) datetime(*struct_time[:6])eksik *. (4) timegm(), utctimetuple(), struct_timemerkezli çözeltiler saniyenin kesirleri bırakın. Bunun gibi açık bir formül kullanabilirsiniz: ts = (d - epoch) / unitbunun yerine.
jfs

1
(5) stz.localize(dt, is_dst=None)örneğin DST geçişleri sırasında belirsiz veya var olmayan yerel zamanlar için bir istisna oluşturur. İstisnadan kaçınmak için, stz.normalize(stz.localize(dt))kesin olmayan sonuçlar döndüren kullanın . (6) datetime () artık bir saniyeyi temsil edemez. Önce geçici bir çözüm olarak "dönemden bu yana saniye" dönüştürün struct_time. (7) time.gmtime(t)aksine calendar.timegm()"doğru" saat dilimi kullanılırsa POSIX dışı giriş beklenebilir. Giriş bunun yerine POSIX ise açık formülü kullanın:gmtime = lambda t: datetime(1970,1,1, tzinfo=utc) + timedelta(seconds=t)
jfs

keşke bu bir tablo, okumak daha kolay (bağlantıda) keşke
MichaelChirico

1
@MichaelChirico, bu cevap " Etikete izin vermiyoruz (ve vermeyeceğiz) <table>. Maalesef. Bu kasıtlı ve tasarım gereği. Hızlı ve kirli bir" masaya "ihtiyacınız varsa, <pre>ASCII düzenini kullanın ." ASCII tablosunun yukarıdaki listeden daha okunabilir olacağına inanmıyorum.
akaihola

talihsiz bir durum. benim oyumu zaten var ... belki cevabınızdaki bağlantıda tabloya referans?
MichaelChirico

25
def local_to_utc(t):
    secs = time.mktime(t)
    return time.gmtime(secs)

def utc_to_local(t):
    secs = calendar.timegm(t)
    return time.localtime(secs)

Kaynak: http://feihonghsu.blogspot.com/2008/02/converting-from-local-time-to-utc.html

BD808'den örnek kullanım : Kaynağınız bir datetime.datetimenesne tise şu şekilde arayın:

local_to_utc(t.timetuple())

5
Kaynağınız datetime.datetime nesnesiyse şu şekilde tarayın: local_to_utc (t.timetuple ())
bd808

2
.timetuple()setleri çağırmak tm_isdstiçin -1; mktime()DST geçişi sırasında % 50 başarısız olma şansı vardır .
jfs

1
Chuck'ın çözümü milisaniye bilgilerini kaybeder.
Luca

21

Dateutil (diğer ilgili sorular için SO üzerinde yaygın olarak tavsiye edilir) ile iyi şanslar yaşıyorum :

from datetime import *
from dateutil import *
from dateutil.tz import *

# METHOD 1: Hardcode zones:
utc_zone = tz.gettz('UTC')
local_zone = tz.gettz('America/Chicago')
# METHOD 2: Auto-detect zones:
utc_zone = tz.tzutc()
local_zone = tz.tzlocal()

# Convert time string to datetime
local_time = datetime.strptime("2008-09-17 14:02:00", '%Y-%m-%d %H:%M:%S')

# Tell the datetime object that it's in local time zone since 
# datetime objects are 'naive' by default
local_time = local_time.replace(tzinfo=local_zone)
# Convert time to UTC
utc_time = local_time.astimezone(utc_zone)
# Generate UTC time string
utc_string = utc_time.strftime('%Y-%m-%d %H:%M:%S')

(Kod, UTC datetime dizesini yerel datetime'a dönüştürmek için bu yanıttan türetilmiştir )


dateutilyerel bir saat dilimi farklı bir utc ofsetine sahipse (uygulamanın geçmiş saat dilimi veritabanını (özellikle Windows) kullanmadığı sistemlerde) (DST geçişleriyle ilgisi yoksa) geçmiş tarihler için başarısız olabilir. pytz+ tzlocalkullanılabilir.
jfs

@ JFSebastian- Bunu duymamıştım- daha fazla bilgiyi nereden alabiliriz?
Yarin

Windows makinesini al, geçmişte farklı utc ofseti olan herhangi bir saat dilimini ayarlayın, örneğin Avrupa / Moskova. Sonuçları pytz ile karşılaştırın . Ayrıca, bu durumda doğru API kullanımından emin olmasam da Ubuntu'da bile başarısız olan bu hatayı test edebilirsiniz .
jfs

Çıktı nedir? Lütfen çıktıyı gönderin.
not2qubit

18

Pytz ile bir örnek daha, ama benim gün kurtardı localize () içerir.

import pytz, datetime
utc = pytz.utc
fmt = '%Y-%m-%d %H:%M:%S'
amsterdam = pytz.timezone('Europe/Amsterdam')

dt = datetime.datetime.strptime("2012-04-06 10:00:00", fmt)
am_dt = amsterdam.localize(dt)
print am_dt.astimezone(utc).strftime(fmt)
'2012-04-06 08:00:00'


7
import time

import datetime

def Local2UTC(LocalTime):

    EpochSecond = time.mktime(LocalTime.timetuple())
    utcTime = datetime.datetime.utcfromtimestamp(EpochSecond)

    return utcTime

>>> LocalTime = datetime.datetime.now()

>>> UTCTime = Local2UTC(LocalTime)

>>> LocalTime.ctime()

'Thu Feb  3 22:33:46 2011'

>>> UTCTime.ctime()

'Fri Feb  4 05:33:46 2011'

mktime(dt.timetuple())DST geçişi sırasında başarısız olabilir . Orada LocalTimezonedocs (en son zaman dilimi tanımı için çalışır, ancak DST (son tarihlerde ilgisiz başarısız olabilir)) içinde
jfs

5

datetime.datetime tercih ediyorsanız:

dt = datetime.strptime("2008-09-17 14:04:00","%Y-%m-%d %H:%M:%S")
utc_struct_time = time.gmtime(time.mktime(dt.timetuple()))
utc_dt = datetime.fromtimestamp(time.mktime(utc_struct_time))
print dt.strftime("%Y-%m-%d %H:%M:%S")

1
Tabii, ama bunu neden tercih ettiğini anlayamıyorum. Sürümümden daha fazla içe aktarma ve 3 tane daha işlev çağrısı gerektirir ...
Tom

% Z ve% z beyaz boşlukları sabit olarak yazdırır.
Pavel Vlasov

2
yanlış. Yerel saat dilimi UTC değilse başarısız olur. mktime()girdi olarak yerel saati bekler. fromtimestamp()utc değil, yerel saati döndürür. Düzeltirseniz, bu ek sorunları görün ( dateutilyalnızca stdlib çözümü çözüm başarısız olabilir)
jfs

5

Basit

Ben böyle yaptım:

>>> utc_delta = datetime.utcnow()-datetime.now()
>>> utc_time = datetime(2008, 9, 17, 14, 2, 0) + utc_delta
>>> print(utc_time)
2008-09-17 19:01:59.999996

Fantezi Uygulama

Eğer süslemek istiyorsanız, bunu bir functor'a dönüştürebilirsiniz:

class to_utc():
    utc_delta = datetime.utcnow() - datetime.now()

    def __call__(cls, t):
        return t + cls.utc_delta

Sonuç:

>>> utc_converter = to_utc()
>>> print(utc_converter(datetime(2008, 9, 17, 14, 2, 0)))
2008-09-17 19:01:59.999996

5
bu, yaz saati uygulamasında işe yaramaz - örneğin, şu anda yaz ve dönüştürdüğünüz tarih kışınsa. ve soru dizeler halinde saklanan tarihleri ​​dönüştürmeyle ilgiliydi ...
Tom

1
Bilginize. Bu yöntemle ilgili en büyük sorun (gün ışığından yararlanma yanında), deltanın birkaç milisaniyede çıkmasıdır. Tüm takvim davetlerim 1 dakika kadar gösteriliyor.
Nostalg.io

4

Şunlarla yapabilirsiniz:

>>> from time import strftime, gmtime, localtime
>>> strftime('%H:%M:%S', gmtime()) #UTC time
>>> strftime('%H:%M:%S', localtime()) # localtime

3

Nasıl -

time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(seconds))

saniye ise Noneyerel saati UTC saatine, başka bir süre ise UTC'ye çevirir.


2

Gün ışığından yararlanma vb.

Yukarıdaki cevapların hiçbiri bana yardımcı olmadı. Aşağıdaki kod GMT için geçerlidir.

def get_utc_from_local(date_time, local_tz=None):
    assert date_time.__class__.__name__ == 'datetime'
    if local_tz is None:
        local_tz = pytz.timezone(settings.TIME_ZONE) # Django eg, "Europe/London"
    local_time = local_tz.normalize(local_tz.localize(date_time))
    return local_time.astimezone(pytz.utc)

import pytz
from datetime import datetime

summer_11_am = datetime(2011, 7, 1, 11)
get_utc_from_local(summer_11_am)
>>>datetime.datetime(2011, 7, 1, 10, 0, tzinfo=<UTC>)

winter_11_am = datetime(2011, 11, 11, 11)
get_utc_from_local(winter_11_am)
>>>datetime.datetime(2011, 11, 11, 11, 0, tzinfo=<UTC>)

2

Http://crsmithdev.com/arrow/ kullanma

arrowObj = arrow.Arrow.strptime('2017-02-20 10:00:00', '%Y-%m-%d %H:%M:%S' , 'US/Eastern')

arrowObj.to('UTC') or arrowObj.to('local') 

Bu kütüphane hayatı kolaylaştırıyor :)


arrow harika: arrow.get (datetime.now (), 'yerel'). - ('utc'). naif
SteveJ

1

Burada başka bir soruya en iyi yanıtı buldum . Yalnızca python yerleşik kitaplıklarını kullanır ve yerel saat diliminizi girmenizi gerektirmez (benim durumumda bir gereklilik)

import time
import calendar

local_time = time.strptime("2018-12-13T09:32:00.000", "%Y-%m-%dT%H:%M:%S.%f")
local_seconds = time.mktime(local_time)
utc_time = time.gmtime(local_seconds)

Arama anahtar kelimelerine bağlı olarak bu soru bağlantılı soru yerine google'da açıldığından cevabı burada yeniden gönderiyorum.


1

Benim projelerden birinde bu kodu var:

from datetime import datetime
## datetime.timezone works in newer versions of python
try:
    from datetime import timezone
    utc_tz = timezone.utc
except:
    import pytz
    utc_tz = pytz.utc

def _to_utc_date_string(ts):
    # type (Union[date,datetime]]) -> str
    """coerce datetimes to UTC (assume localtime if nothing is given)"""
    if (isinstance(ts, datetime)):
        try:
            ## in python 3.6 and higher, ts.astimezone() will assume a
            ## naive timestamp is localtime (and so do we)
            ts = ts.astimezone(utc_tz)
        except:
            ## in python 2.7 and 3.5, ts.astimezone() will fail on
            ## naive timestamps, but we'd like to assume they are
            ## localtime
            import tzlocal
            ts = tzlocal.get_localzone().localize(ts).astimezone(utc_tz)
    return ts.strftime("%Y%m%dT%H%M%SZ")

0

Python3'te:

pip install python-dateutil

from dateutil.parser import tz

mydt.astimezone(tz.gettz('UTC')).replace(tzinfo=None) 

Bu işe yaramaz gibi görünüyor, bir ValueError istisnası yükseltir: ValueError: astimezone () saf bir tarih
saatine

Olması gereken: from dateutil import tz
Javier

-3

Nasıl -

time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(seconds))

saniye ise Noneyerel saati UTC saatine, başka bir süre ise UTC'ye çevirir.


1
Bu yardımcı olmaz, soru belirli bir yerel saat dizesini bir utc dizesine dönüştürmekti.
Tom
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.