正規表現を使って、日付っぽい文字列をそれらしくdatetimeに押し込める
さくらインターネットのさくらのブログで驚いたのは、エントリーの公開日時を設定する際、ユーザーに日付をテキストで入力させるというところでした。私の常識では、ユーザーに直接入力させるなんて、危険極まりないからしてはならない。2009-03-15 12:15:00と入力してほしいのに、想像を絶するような、ありえない文字列を投げ込まれたりする。ところがさくらのブログでは、ユーザーに文字列として日付時刻を入力させるのです。驚いて、そして今はもうネットでブログなんてやろうというユーザーになると、これくらいの要求には軽く応えられるのだと、そういう時代になったことを理解したのでした。
というわけで、私の作っているK-enq.tdでも、日付時刻の設定は、ユーザーに文字列として入力してもらうことにしました。
で、それを正規表現でばらして、datetimeに押し込んで、datetime型のオブジェクトにしようと思って、試しに正規表現を書いてみました。それが以下のものです。
import re import datetime redt = re.compile(u'(\d{4})\D?([01]?\d)\D?([0-3]?\d)\D?([0-2]?\d?)\D?([0-5]?\d?)\D?([0-5]?\d?)') def strtdatetime(string): if isinstance(string, basestring): m = redt.match(string) if m is None: return u'' else: l = [2001, 01, 01, 00, 00, 00] for i in range(len(m.groups())): try: l[i] = int(m.group(i + 1)) except ValueError: l[i] = 00 return datetime.datetime(l[0], l[1], l[2], l[3], l[4], l[5]) else: return u''
最終的に、これはなんらかのクラスのメソッドにする予定ですが、今はまだただの関数です。日付時刻を表現する文字列を受け取って、それをdatetimeオブジェクトにして返します。もし文字列が不正、つまり正規表現にマッチしなかったら、長さ0の文字列を返します。場合によってはdatetime.datetime.today()を返してもいいのかも知れないけど、今作ってるシステムでは、開始日および終了日がブランクになることもあるから、長さ0の文字列を返すようにしています。
これ、実験してみたところ、それっぽく働いてくれて、区切り文字は数字以外ならなんでもいいっていい加減さだから、2009/03/15でも大丈夫。20090315みたいにしても、適当にばらしてくれます。まあ、いい加減なものなので、誤動作誤判定はいくらでもあるでしょうが、それは気にしないことにします。