it-swarm.it

Come posso convertire l'ora locale in UTC in Python?

Come faccio a convertire un datetime stringa in ora locale a un stringa in ora UTC?

Sono sicuro di averlo già fatto, ma non riesco a trovarlo e SO si spera che mi aiuti (e altri) a farlo in futuro.

Chiarimento: Ad esempio, se ho 2008-09-17 14:02:00 nel mio fuso orario locale (+10), mi piacerebbe generare una stringa con l'equivalente UTC time: 2008-09-17 04:02:00.

Inoltre, da http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/ , nota che in generale questo non è possibile come con DST e altri problemi non c'è una conversione univoca dall'ora locale all'ora UTC.

248
Tom

Grazie a @rofly, la conversione completa da stringa a stringa è la seguente:

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

Il mio riassunto delle funzioni time/calendar:

time.strptime
stringa -> Tupla (nessun fuso orario applicato, quindi corrisponde alla stringa)

time.mktime
ora locale Tuple -> secondi da Epoch (sempre ora locale)

time.gmtime
secondi da Epoch -> Tuple in UTC

calendar.timegm
Tupla in UTC -> secondi da Epoch

time.localtime
secondi da Epoch -> Tuple nel fuso orario locale

60
Tom

Innanzitutto, analizzare la stringa in un oggetto datetime ingenuo. Questa è un'istanza di datetime.datetime con nessuna informazione sul fuso orario associata. Consultare la documentazione per datetime.strptime per informazioni sull'analisi della stringa della data.

Utilizza il modulo pytz , che viene fornito con un elenco completo di fusi orari + UTC. Scopri cosa è il fuso orario locale, costruisci un oggetto fuso orario da esso e manipolalo e collegalo al datetime ingenuo.

Infine, usa il metodo datetime.astimezone() per convertire il datetime in UTC.

Codice sorgente, utilizzando il fuso orario locale "America/Los_Angeles", per la stringa "2001-2-3 10:11:12":

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)

Da lì, puoi utilizzare il metodo strftime() per formattare il datetime UTC come necessario:

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

La funzione utcnow () del modulo datetime può essere utilizzata per ottenere l'ora UTC corrente.

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

Come il link citato sopra da Tom: http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/ dice:

UTC è un fuso orario senza l'ora legale e comunque un fuso orario senza modifiche di configurazione nel passato.

Misura sempre e salva il tempo in UTC

Se è necessario registrare dove è stata presa l'ora, conservarla separatamente. Non memorizzare l'ora locale + informazioni sul fuso orario!

NOTE - Se qualcuno dei tuoi dati si trova in una regione che utilizza l'ora legale, usa pytz e dai un'occhiata alla risposta di John Millikin.

Se si desidera ottenere l'ora UTC da una determinata stringa e avere la fortuna di trovarsi in una regione del mondo che non utilizza l'ora legale o si dispone di dati che sono solo sfalsati da UTC senza applicare l'ora legale:

-> utilizzando l'ora locale come base per il valore di offset:

>>> # 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'

-> Oppure, da un offset noto, usando datetime.timedelta ():

>>> 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'

Se sei pronto ad accettare le conversioni del fuso orario, leggi questo:

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

111
monkut

Ecco un riepilogo delle comuni conversioni temporali Python.

Alcuni metodi rilasciano frazioni di secondi e sono contrassegnati con (s). È possibile utilizzare una formula esplicita come ts = (d - Epoch) / unit (grazie jfs).

  • struct_time (UTC) → POSIX (s):
    calendar.timegm(struct_time)
  • Data/ora Naïve (locale) → POSIX (s):
    calendar.timegm(stz.localize(dt, is_dst=None).utctimetuple())
    (eccezione durante le transizioni DST, vedi commento da jfs)
  • Data/ora Naive (UTC) → POSIX (s):
    calendar.timegm(dt.utctimetuple())
  • Consapevole datetime → POSIX (s):
    calendar.timegm(dt.utctimetuple())
  • POSIX → struct_time (UTC, s):
    time.gmtime(t)
    (vedi commento di jfs)
  • Data/ora originale (locale) → struct_time (UTC, s):
    stz.localize(dt, is_dst=None).utctimetuple()
    (eccezione durante le transizioni DST, vedi commento da jfs)
  • Naïve datetime (UTC) → struct_time (UTC, s):
    dt.utctimetuple()
  • Aware datetime → struct_time (UTC, s):
    dt.utctimetuple()
  • POSIX → Data/ora Naïve (locale):
    datetime.fromtimestamp(t, None)
    (potrebbe non riuscire in determinate condizioni, vedere il commento di jfs qui sotto)
  • struct_time (UTC) → Naive time (locale, s):
    datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz).replace(tzinfo=None)
    (non può rappresentare secondi bisestili, vedi commento da jfs)
  • Data/ora Naïve (UTC) → Data/ora Naïve (locale):
    dt.replace(tzinfo=UTC).astimezone(tz).replace(tzinfo=None)
  • A data-ora consapevole → Data/ora naïve (locale):
    dt.astimezone(tz).replace(tzinfo=None)
  • POSIX → Naïve datetime (UTC):
    datetime.utcfromtimestamp(t)
  • struct_time (UTC) → Naive time (UTC, s):
    datetime.datetime(*struct_time[:6])
    (non può rappresentare secondi bisestili, vedi commento da jfs)
  • Data/ora Naïve (locale) → Data/ora Naïve (UTC):
    stz.localize(dt, is_dst=None).astimezone(UTC).replace(tzinfo=None)
    (eccezione durante le transizioni DST, vedi commento da jfs)
  • Aware datetime → Naïve datetime (UTC):
    dt.astimezone(UTC).replace(tzinfo=None)
  • POSIX → A tempo pieno:
    datetime.fromtimestamp(t, tz)
    (potrebbe non riuscire per i fusi orari non-pytz)
  • struct_time (UTC) → Aware datetime (s):
    datetime.datetime(struct_time[:6], tzinfo=UTC).astimezone(tz)
    (non può rappresentare secondi bisestili, vedi commento da jfs)
  • Data/ora anonima (locale) → Data/ora compatibile:
    stz.localize(dt, is_dst=None)
    (eccezione durante le transizioni DST, vedi commento da jfs)
  • Naïve datetime (UTC) → Aware datetime:
    dt.replace(tzinfo=UTC)

Fonte: taaviburns.ca

31
akaihola
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)

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

Esempio di utilizzo da bd808 : Se la tua origine è un datetime.datetime oggetto t, chiama come:

local_to_utc(t.timetuple())
23
Chuck Callebs

Sto avendo fortuna con dateutil (che è ampiamente raccomandato su SO per altre domande correlate):

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

(Il codice è stato derivato da questa risposta a Converti la stringa datetime UTC in datetime locale )

18
Yarin

Un altro esempio di pytz, ma include localize (), che mi ha salvato la giornata.

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'
17

Ho avuto il maggior successo con python-dateutil :

from dateutil import tz

def datetime_to_utc(date):
    """Returns date in UTC w/o tzinfo"""
    return date.astimezone(tz.gettz('UTC')).replace(tzinfo=None) if date.tzinfo else date
12
Shu Wu
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'
7
Scipythonee

se preferisci datetime.datetime:

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")
5
user235042

Puoi farlo con:

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

Per aggirare il risparmio della luce diurna, ecc.

Nessuna delle risposte precedenti mi ha particolarmente aiutato. Il codice qui sotto funziona per GMT.

def get_utc_from_local(date_time, local_tz=None):
    assert date_time.__class__.__== '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
Dantalion

Che ne dite di - 

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

se seconds è None allora converte l'ora locale in ora UTC, altrimenti converte il tempo passato in UTC.

2
Anonymous fool

Utilizzando http://crsmithdev.com/arrow/

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

Questa libreria rende la vita facile :)

2
Yash

Semplice

L'ho fatto in questo modo:

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

Fancy Implementation

Se vuoi essere elegante, puoi trasformarlo in un funtore:

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

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

Risultato: 

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

In python3:

pip install python-dateutil

from dateutil.parser import tz

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

Ho trovato la risposta migliore su un'altra domanda qui . Utilizza solo librerie incorporate Python e non richiede di inserire il fuso orario locale (un requisito nel mio caso) 

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)

Sto ripubblicando la risposta qui poiché questa domanda appare in google al posto della domanda collegata a seconda delle parole chiave di ricerca.

0
franksands