やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Pythonのfeedparserで取得したRSS/Atomの日付をUTCにしたいが、死ぬほど大変そう

 RSSの日付データはテキスト。その表現形式はUTC,JSTなどがありうる。これらをすべてYYYY-mm-ddTHH:MM:SSZ形式にしたい。SQLite3DBに登録するために。

やりたいこと

 いかなる日付テキストもUTC時刻にしてYYYY-mm-ddTHH:MM:SSZ形式のテキストにしたい。以下のような簡単なコードで。

feed.entries[i].published_parsed.format('%Y-%m-%dT%H:%M:%SZ')

 前回のようにRSS/Atomによって日付テキストの書式規格が異なる。また、同じ規格であっても:の有無など微妙に異なる書式もあるが規格のうちである。それらに完全対応したい。

結論

 Python3.7以降でないと無理っぽい。3.6でもいけるかも。いずれにせよ、私の環境3.5.3では無理。

日時の扱いが難しすぎる件

RSS/Atomにおける日付形式がバラバラ

  1. RSS/Atomで日付をテキストから取得する
  2. RSS/Atomの規格によって日付書式が異なる(UTC,JSTなど時刻自体も異なる場合もある)

RSS/Atomパーサにおける日付形式がtime.struct_time

 Pythonパッケージfeedparserの話。RSS/Atomからデータを取得するものだが、日付の型が文字列またはtime.struct_timeなせいで、タイムゾーンが簡単に扱えず、JSTUTCなどの時刻変換がむずかしい。

Pythonで日時を扱う方法が統一されておらず難しい

 Pythonで日時を扱う方法は複数あるようだ。ふつう日時はdatetimeで扱うことが多いと思うが、feedparserではtime.struct_timeで取得されるらしい。

 time.struct_timeタイムゾーンを取得し、UTCに変換し、フォーマットを指定したい。これを簡単にやる方法はなさそう。それどころか、環境によってはPython3.6以降でないとタイムゾーンが扱えない。私の環境では扱えなかった。

 つまり、time.struct_timeで取得できるfeedparser entries[i].published_parsedでは、UTC時刻に変換できない。

文字列→日付型(タイムゾーン:があるとエラー)

 では、文字列から日付型に変換するのはどうか?

 feedparser entries[i].publishedで文字列として取得し、文字列から時刻変換し、書式を指定すればいい。

 これを実装する方法がわからない。というか、文字列からdatetime型へ変換するときのパターンが無限にあるだろうことから、網羅できないことが懸念される。スペースひとつ違うだけでエラーになる。また、時刻変換もある。JSTなどからUTCへ変換するなど、異なる時刻体系に変換する方法を調べねばならない。その場合分けも大変そう。

 わからないことが多すぎて、めっちゃ大変。そして、自前で実装せねばならないことが多すぎる。ありえない。

 タイムゾーン書式%zは、[+-][0-9]{4}という書式でないと受け付けない。しばしば、[+-][0-9]{2}:[0-9]{2}のように時と分の間にコロン:が入る書式もある。それはエラーになる……。それなのにprintで表示されるのはコロン付きという謎仕様。

import datetime
dt1 = datetime.datetime.strptime('2019-01-01T12:00:00+09:00', '%Y-%m-%dT%H:%M:%S%z') # エラー
dt1 = datetime.datetime.strptime('2019-01-01T12:00:00+0900', '%Y-%m-%dT%H:%M:%S%z') # OK
print(dt1)
ValueError: time data '2019-01-01T12:00:00+09:00' does not match format '%Y-%m-%dT%H:%M:%S%z'

 ちなみに、RSS1.0は:付きの書式っぽい。

 よって、Python3.7より前ではRSS1.0の日時テキストを日付型に変換できない……嘘だろ……。ISO-8601形式チェックすらできないとかクソすぎてクソ。

 ただし、Python3.7からは:に対応するらしい。そんな新しい環境は入っていない……。

Python最新環境をつくる

 なら、新しいPython環境を作ったほうが早いと思うだろうが、それこそ超絶に大変。地獄と呼ぶにふさわしい苦行が待っている。

 docker,anyenv,pyenv,venvなどの事前設備を整え、さらにPythonビルド前にビルドツール各種の用意をし、Pythonで使うライブラリTk,SQLite3の最新版を用意し、その上でPythonをビルドする。できたら次は必要なパッケージをインストール。これだけ大変なことをするのに、一体どれだけの学習と手間が必要だろうか。たかが日付変換のためにやることではない。

  1. docker,anyenv,pyenv,venvなどの事前設備を整える(どれを使い使わぬかの判断から)
  2. ビルドツール各種を用意する
  3. Pythonで使うライブラリTk,SQLite3の最新版を用意する(自前ビルド)
  4. パッケージ仮想化環境をつくる(venv)
  5. Pythonパッケージをインストールする(pip)
  6. 仮想化環境を有効化する
  7. パッケージを使ったPythonコードを書く

所感

 これだからPythonは嫌い。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux