In Python 3.3 +, email
messaggio può analizzare le intestazioni per voi:
import email
import email.policy
headers = email.message_from_file(file, policy=email.policy.default)
print(headers.get('date').datetime)
# -> 2009-11-16 13:32:02+01:00
Dal Python 3.2+, funziona se si sostituisce %Z
con %z
:
>>> from datetime import datetime
>>> datetime.strptime("Mon, 16 Nov 2009 13:32:02 +0100",
... "%a, %d %b %Y %H:%M:%S %z")
datetime.datetime(2009, 11, 16, 13, 32, 2,
tzinfo=datetime.timezone(datetime.timedelta(0, 3600)))
o utilizzando email
pacchetto (Python 3.3+):
>>> from email.utils import parsedate_to_datetime
>>> parsedate_to_datetime("Mon, 16 Nov 2009 13:32:02 +0100")
datetime.datetime(2009, 11, 16, 13, 32, 2,
tzinfo=datetime.timezone(datetime.timedelta(0, 3600)))
se differenza UTC è specificato come -0000
allora restituisce un oggetto datetime ingenuo che rappresenta il tempo in UTC, altrimenti restituisce un oggetto datetime con il set tzinfo
corrispondente.
Per analizzare rfc 5322 date-time string su versioni precedenti di Python (2.6+):
from calendar import timegm
from datetime import datetime, timedelta, tzinfo
from email.utils import parsedate_tz
ZERO = timedelta(0)
time_string = 'Mon, 16 Nov 2009 13:32:02 +0100'
tt = parsedate_tz(time_string)
#NOTE: mktime_tz is broken on Python < 2.7.4,
# see https://bugs.python.org/issue21267
timestamp = timegm(tt) - tt[9] # local time - utc offset == utc time
naive_utc_dt = datetime(1970, 1, 1) + timedelta(seconds=timestamp)
aware_utc_dt = naive_utc_dt.replace(tzinfo=FixedOffset(ZERO, 'UTC'))
aware_dt = aware_utc_dt.astimezone(FixedOffset(timedelta(seconds=tt[9])))
print(aware_utc_dt)
print(aware_dt)
# -> 2009-11-16 12:32:02+00:00
# -> 2009-11-16 13:32:02+01:00
dove FixedOffset
is based on tzinfo
subclass from the datetime
documentation:
class FixedOffset(tzinfo):
"""Fixed UTC offset: `time = utc_time + utc_offset`."""
def __init__(self, offset, name=None):
self.__offset = offset
if name is None:
seconds = abs(offset).seconds
assert abs(offset).days == 0
hours, seconds = divmod(seconds, 3600)
if offset < ZERO:
hours = -hours
minutes, seconds = divmod(seconds, 60)
assert seconds == 0
#NOTE: the last part is to remind about deprecated POSIX
# GMT+h timezones that have the opposite sign in the
# name; the corresponding numeric value is not used e.g.,
# no minutes
self.__name = '<%+03d%02d>GMT%+d' % (hours, minutes, -hours)
else:
self.__name = name
def utcoffset(self, dt=None):
return self.__offset
def tzname(self, dt=None):
return self.__name
def dst(self, dt=None):
return ZERO
def __repr__(self):
return 'FixedOffset(%r, %r)' % (self.utcoffset(), self.tzname())
Sì, quelle funzioni sembrano essere state spostate su utils e l'e-mail va bene per l'uso. Grazie. – gruszczy
Ciò non produrrà un valore preciso. 'time.mktime' assume una tupla temporale locale e la funzione parsedate non tiene conto del fuso orario:' time.mktime (email.utils.parsedate ('Mon, 16 Nov 2009 13:32:02 +0900')) == time.mktime (email.utils.parsedate ('Mon, 16 Nov 2009 13:32:02 +0100')) 'restituisce' True'. Tagging @gruszczy nel caso in cui si basi su questo metodo. –
'mktime + timezone' può produrre valori errati per date passate o se il fuso orario ha transizioni DST:' time.timezone! = Time.altzone'. Usa 'tt = parsedate_tz (date_str); timestamp = calendar.timegm (tt) - tt [9] 'invece. – jfs