RFC2822ライブラリforPython

RFC2822はWebAppがはやってきた訳でなかなか使う場面も多いかと思う.

自分もtwitterいじってて,相互変換できたほうが良さそうなので簡単なライブラリにしてみた.

  • mylib/rfc2822.py
#coding:utf-8
# need python 2.4 or newer, maybe!

import datetime

# timezone class for JST
class JST (datetime.tzinfo):
    def utcoffset (self, dt=None):
        # default offset of this timezone from UTC
        return datetime.timedelta (hours=9)
    def dst (self, dt=None):
        # offset in daylight saving time
        return datetime.timedelta (hours=9)
    def tzname (self, dt=None):
        # name of this timezone
        return "JST"

class UTC (datetime.tzinfo):
    def utcoffset (self, dt=None):
        return datetime.timedelta (hours=0)
    def dst (self, dt=None):
        return datetime.timedelta (hours=0)
    def tzname (self, dt=None):
        return "UTC"

def date_to_rfc2822 (d):
    # d : datetime object with timezone
    from time import mktime
    import email
    from email.utils import formatdate, mktime_tz
    import datetime
    if not d.tzinfo:
        print 'date_to_rfc2822 : argument d must be aware datetime object'
        raise

    tzdelta = d.tzinfo.utcoffset ().seconds
    dt_tz = datetime.datetime.timetuple (d) + (tzdelta,)
    return formatdate (mktime_tz (dt_tz))

def rfc2822_to_date (t, tz=UTC ()):
    # t : string
    # this argument assumes string expression of RFC2822, i.e. 'WeekDay Month Day HH:MM:SS UTCOffset Year'
    # tz : tzinfo object
    # tz detetmines the timezone of the returning string
    import email
    from email.utils import parsedate_tz, mktime_tz
    import datetime
    from time import mktime
    
    return datetime.datetime.fromtimestamp(mktime_tz (parsedate_tz (t)), tz)

で,使い方

>>> from rfc2822 import rfc2822_to_date, date_to_rfc2822, JST, UTC
>>> from datetime import datetime
>>>
>>> date_to_rfc2822 (datetime.now (UTC ()))
'Tue, 25 Aug 2009 18:43:28 -0000'
>>> date_to_rfc2822 (datetime.now (JST ()))
'Tue, 25 Aug 2009 18:43:32 -0000'
>>> rfc2822_to_date ('Tue Aug 25 06:41:01 +0000 2009', JST ())
datetime.datetime(2009, 8, 25, 15, 41, 1, tzinfo=<rfcutils.JST object at 0x8cd70>)
>>> rfc2822_to_date ('Tue Aug 25 06:41:01 +0200 2009', JST ())
datetime.datetime(2009, 8, 25, 13, 41, 1, tzinfo=<rfcutils.JST object at 0xbd530>)
>>> rfc2822_to_date ('Tue Aug 25 06:41:01 +0200 2009')
datetime.datetime(2009, 8, 25, 4, 41, 1, tzinfo=<rfcutils.UTC object at 0xbd4d0>)
>>> rfc2822_to_date ('Tue Aug 25 06:41:01 +0000 2009')
datetime.datetime(2009, 8, 25, 6, 41, 1, tzinfo=<rfcutils.UTC object at 0xbd4d0>)

ポイントはtimezoneを指定すること.

date_to_rfc2822のクラスは必ずtzinfoフィールドを持つようにしなければいけない.

そのために,利用者が簡単に使えるようライブラリ内にJST,UTCクラスを用意している.

必要に応じて自分のタイムゾーンに合ったdatetime.tzinfoを継承したクラスを作ればいくらでも対応できる.*1