BLOGサブスレッドの日常

2017.08.14

今さら1900年問題

tama

半年以上ぶり、2017年初登場の tama です。
お盆休みですねー。
ふだんなかなかコードを書く時間が取れない女子大生してますが、
ひさしぶりにゴソゴソしてさっそくハマったので共有しておきます…

Excel に Excel の得意なことをさせる

巷では Excel を方眼紙にしたりオブジェクトを置くキャンバスにしたり間違った使い方がはびこってますが。
そういうのはそれぞれ Word や PowerPoint に任せればいいと思うんです。
Excel はあくまで表計算ソフト。表計算させてこそ真価を発揮します。
(弊社は給与計算や帳簿は専門ソフトでなく代表が手塩にかけて育てたExcelで管理しています)

と言いつつ Excel を「ちょっと使い勝手のいい Access 代わり」にしていたら事件が起こりました。

データ編集エディタとしての Excel

DBにつっこむようなデータをマトリックスで編集したいシーンってあると思うんです。

こういうやつです。例えば日々 bot がつぶやく一言を一括編集するだとか。

そいでそれを Python で扱える形式にして出力したりだとか。
Pythonのソースファイルに辞書(dict)として貼り付けてデータとして使います。
(半年分一気にデータを用意しておくのだけど、途中で編集する可能性もあるのでSQL文にして
DBに入れるのでなくソースとしてgitで履歴も管理したい的な。
なんかいろいろ手間を惜しんだ結果こういうサボった運用になるプライベートなプロジェクト)

落とし穴

Excel の日付値は1900年1月1日からの経過日で、1900年1月1日は 1 です。
なので Python の datetime.dateオブジェクトの ordinal値や timedelta を使えば同じ値が得られるはずです。理論上は。

datetime.date(2017, 8, 14).toordinal() - datetime.date(1900, 1, 1).toordinal() + 1 ⇒ 42960
(datetime.date(2017, 8, 14) - datetime.date(1900, 1, 1)).days + 1 ⇒ 42960

ち が う や ん

(datetime.date(1901, 1, 1) - datetime.date(1900, 1, 1)).days + 1 ⇒ 366

???

これ、1900年をうるう年として扱うか否かという 仕様の問題 みたいです。
これを単純にバグと言いきれないのは、マイクロソフトは互換性を鑑みてあえてこの不具合のような実装を採用しているからです。
参考
(「Excel 1900年」などでぐぐると 1900/2/29 に関する記事などもヒットします)

しょうがないので Python 側の処理で対処します。

def toserial(date):
    return date.toordinal() - datetime.date(1900, 1, 1).toordinal() + 2

だから何?

えっと、、現場からは以上です。

この記事を書いた人

tama