home changes contents help options

198:文字列を日時に変換する

time

time モジュールの strptime 関数を用いると 'Wed Jan 28 21:43:32 2009' のような文字列から time.struct_time インスタンスを得ることができます。

>>> import time
>>> time.strptime('Wed Jan 28 21:43:32 2009')
(2009, 1, 28, 21, 43, 32, 2, 28, -1)

第 2 引数 format にフォーマットを指定することで任意の文字列を time.struct_time インスタンスに変換することもできます。フォーマットについては time モジュールのドキュメントを参照してください。

>>> time.strptime('2009-01-28', '%Y-%m-%d')
(2009, 1, 28, 0, 0, 0, 2, 28, -1)

datetime

datetime モジュールの datetime クラスには strptime クラスメソッドが存在し、文字列からインスタンスを得ることができるようになっています。使用方法は第 2 引数 format がデフォルト値を持たない以外は time.strptime と同じです。フォーマットについては time モジュールのドキュメントを参照してください。

>>> import datetime
>>> datetime.datetime.strptime('Wed Jan 28 21:43:32 2009', "%a %b %d %H:%M:%S %Y")
datetime.datetime(2009, 1, 28, 21, 43, 32)

Python 2.4 以前では strptime クラスメソッドが存在しませんが、time.strptime との合わせ技で同じことが可能です。

>>> import time
>>> import datetime
>>> datetime.datetime(*time.strptime('2009-01-28', '%Y-%m-%d')[0:6])
datetime.datetime(2009, 1, 28, 0, 0)

email.utils

メールで用いられている RFC 2822 形式の日付 (例:「Mon, 20 Nov 1995 19:12:08 -0500」)を読む関数が email.utils モジュールに用意されています。

>>> from email.utils import *
>>> parsedate("Mon, 20 Nov 1995 19:12:08 -0500")
(1995, 11, 20, 19, 12, 8, 0, 1, -1)
>>> parsedate_tz("Mon, 20 Nov 1995 19:12:08 -0500")
(1995, 11, 20, 19, 12, 8, 0, 1, -1, -18000)

dateutil

サードパーティー製モジュール dateutildatetime モジュールをより便利なものとしてくれます。ここでは、さまざまな形式の日時文字列を datetime.datetime インスタンスに変換する関数 parse を紹介します。

>>> from dateutil.parser import parse
>>> parse('Tue Apr 10 04:54:42 JST 2007')
datetime.datetime(2007, 4, 10, 4, 54, 42)
>>> parse('Tue, 10 Apr 2007 04:54:42 +0900')
datetime.datetime(2007, 4, 10, 4, 54, 42, tzinfo=tzoffset(None, 32400))
>>> parse('Sun, 10 Apr 2007 04:54:42 JST')
datetime.datetime(2007, 4, 10, 4, 54, 42)
>>> parse('Sun, 09 Apr 2007 19:54:42 GMT')
datetime.datetime(2007, 4, 9, 19, 54, 42, tzinfo=tzutc())
>>> parse('2007-04-10T04:54:42+09:00')
datetime.datetime(2007, 4, 10, 4, 54, 42, tzinfo=tzoffset(None, 32400))
>>> parse('2007/04/10 04:54:42')
datetime.datetime(2007, 4, 10, 4, 54, 42)
>>> parse('2007/04/10')
datetime.datetime(2007, 4, 10, 0, 0)
>>> parse('20070410045442')
datetime.datetime(2007, 4, 10, 4, 54, 42)
>>> parse('04:52:42')
datetime.datetime(2009, 1, 28, 4, 52, 42)
>>> parse('04/10')
datetime.datetime(2009, 4, 10, 0, 0)

JST タイムゾーンにも対応するには tzinfos 引数に 'JST' キーを持つ辞書を渡します。値は +09:00 を示す秒数とします。もしくは datetime.tzinfo のサブクラスのインスタンスとします。JST を表す tzinfo サブクラスも用意されていて dateutil.tz.gettz('Asia/Tokyo') で得られます。

>>> parse('Sun, 10 Apr 2007 04:54:42 JST', tzinfos={'JST': 3600*9})
datetime.datetime(2007, 4, 10, 4, 54, 42, tzinfo=tzoffset('JST', 32400))
>>>
>>> from dateutil.tz import gettz
>>> JST = gettz('Asia/Tokyo')
>>> parse('Sun, 10 Apr 2007 04:54:42 JST', tzinfos={'JST': JST})
datetime.datetime(2007, 4, 10, 4, 54, 42, tzinfo=tzfile('Asia/Tokyo'))

'H19.04.10' などの和暦については解析できませんでした。これは日本生まれの Ruby ならではですね。

和暦

Ruby の Time.parse や Date.parse は 'H19.04.10' といった和暦にも対応しています。と、いうわけで Python でもこの和暦を読むべく、関数作成に挑んでみました。

import re
import datetime

_wareki = re.compile(ur'''
        (?P<gengou>[MTSH])
        (?P<year>\d+)
        \.
        (?P<month>\d{1,2})
        \.
        (?P<date>\d{1,2})
        (
          .+?
          (?P<hour>\d{1,2})
          (
            .*?:.*?
            (?P<minite>\d{1,2})
            (
                .*?:.*?
                (?P<second>\d{1,2})
            )?
          )?
        )?
        ''',
        re.VERBOSE | re.IGNORECASE)
_gengou = {'M': 1867, 'T': 1911, 'S': 1925, 'H': 1988}
def wareki(s):
    mo = _wareki.match(s)
    if mo:
        year = int(mo.group('year')) + _gengou[mo.group('gengou').upper()]
        month = int(mo.group('month'))
        date = int(mo.group('date'))
        hour = mo.group('hour')
        hour = int(hour) if hour else 0
        minite = mo.group('minite')
        minite = int(minite) if minite else 0
        second = mo.group('second')
        second = int(second) if second else 0
        return datetime.datetime(year, month, date, hour, minite, second)
    return None