メールから日付を取得しようとしています。最初は簡単です:
message = email.parser.Parser().parse(file)
date = message['Date']
print date
そして私は受け取ります:
'Mon, 16 Nov 2009 13:32:02 +0100'
しかし、Nice datetimeオブジェクトが必要なので、次を使用します。
datetime.strptime('Mon, 16 Nov 2009 13:32:02 +0100', '%a, %d %b %Y %H:%M:%S %Z')
これはValueError, since %Z isn't format for +0100
を発生させます。しかし、ドキュメントでタイムゾーンの適切な形式を見つけることができません。ゾーンにはこの%Z
しかありません。誰かがそれについて私を助けることができますか?
_email.utils
_にはRFC2822形式のparsedate()
関数がありますが、私が知る限り、これは非推奨ではありません。
_>>> import email.utils
>>> import time
>>> import datetime
>>> email.utils.parsedate('Mon, 16 Nov 2009 13:32:02 +0100')
(2009, 11, 16, 13, 32, 2, 0, 1, -1)
>>> time.mktime((2009, 11, 16, 13, 32, 2, 0, 1, -1))
1258378322.0
>>> datetime.datetime.fromtimestamp(1258378322.0)
datetime.datetime(2009, 11, 16, 13, 32, 2)
_
ただし、parsedate
メソッドはタイムゾーンを考慮せず、_time.mktime
_は常に現地時間のタプルを想定していることに注意してください ここ 。
_>>> (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'))
True
_
したがって、タイムゾーンを解析し、現地の時差も考慮する必要があります。
_>>> REMOTE_TIME_ZONE_OFFSET = +9 * 60 * 60
>>> (time.mktime(email.utils.parsedate('Mon, 16 Nov 2009 13:32:02 +0900')) +
... time.timezone - REMOTE_TIME_ZONE_OFFSET)
1258410122.0
_
使用 email.utils.parsedate_tz(date)
:
msg=email.message_from_file(open(file_name))
date=None
date_str=msg.get('date')
if date_str:
date_Tuple=email.utils.parsedate_tz(date_str)
if date_Tuple:
date=datetime.datetime.fromtimestamp(email.utils.mktime_tz(date_Tuple))
if date:
... # valid date found
Python 3.3+では、email
メッセージでヘッダーを解析できます。
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
Python 3.2+なので、%Z
を%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)))
または、email
パッケージ(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)))
uTCオフセットが-0000
として指定されている場合は、UTCで時刻を表す単純な日時オブジェクトを返します。それ以外の場合は、対応するtzinfo
が設定された認識可能な日時オブジェクトを返します。
解析するには rfc 5322 date-time string 以前の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
ここで FixedOffset
はtzinfo
ドキュメントのdatetime
サブクラスに基づいています :
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())
python 3.3+の場合、parsedate_to_datetime関数を使用できます:
>>> 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)))
公式ドキュメント:
Format_datetime()の逆。 parsedate()と同じ関数を実行しますが、成功すると日時を返します。入力日付のタイムゾーンが-0000の場合、その日時は単純な日時になります。日付がRFCに準拠している場合は、UTCでの時刻を表しますが、日付が来るメッセージの実際のソースタイムゾーンは示されません。から。入力日付に他の有効なタイムゾーンオフセットがある場合、その日時は、対応するタイムゾーンtzinfoを持つ認識日時になります。バージョン3.3の新機能。
やってみました
rfc822.parsedate_tz(date) # ?
RFC822の詳細、 http://docs.python.org/library/rfc822.html
非推奨になりました(parsedate_tzは現在 email.utils.parsedate_tz
)、しかし。
しかし、おそらくこれらの答えが役立ちます:
# Parses Nginx' format of "01/Jan/1999:13:59:59 +0400"
# Unfortunately, strptime doesn't support %z for the UTC offset (despite what
# the docs actually say), hence the need # for this function.
def parseDate(dateStr):
date = datetime.datetime.strptime(dateStr[:-6], "%d/%b/%Y:%H:%M:%S")
offsetDir = dateStr[-5]
offsetHours = int(dateStr[-4:-2])
offsetMins = int(dateStr[-2:])
if offsetDir == "-":
offsetHours = -offsetHours
offsetMins = -offsetMins
return date + datetime.timedelta(hours=offsetHours, minutes=offsetMins)
正しい現地時間を取得したい人のために、これが私がしたことです:
from datetime import datetime
from email.utils import parsedate_to_datetime
mail_time_str = 'Mon, 16 Nov 2009 13:32:02 +0100'
local_time_str = datetime.fromtimestamp(parsedate_to_datetime(mail_time_str).timestamp()).strftime('%Y-%m-%d %H:%M:%S')
print(local_time_str)