魂の生命の領域

AWS とか Python とか本読んだ感想とか哲学とか書きます

datetime を使わずに時間を足す

こんばんは。

とある都合で時間を全部足したくなってきましたが、私の使っている Mac には Office が入っていません。 なので Python でやりました。 なぜか datetime モジュールを使わずにやりました( datetime 型は単純な足し算ができないのでそこで考えるのが面倒になった)。

from functools import reduce

# 足したい時間 MM:SS 形式
time_list = [
    '3:14',
    '10:35',
    '5:25',
]

# (MM, SS) の tuple にして足していく
tmp_result = reduce(
    lambda x, y: (x[0] + y[0], x[1] + y[1]),
    map(lambda x: (int(x.split(':')[0]), int(x.split(':')[1])), time_list)
)

# 繰り上がりをいい感じに処理して HH:MM:SS 形式にする
minute, second = divmod(tmp_result[1], 60)
hour, minute = divmod(tmp_result[0] + minute, 60)
result = f'{hour}:{minute}:{second}'

print(result) # 0:19:14

せっかくなので少し解説します。

まず最初の時点で MM:SS 形式の時間の足し算しかしないように書きました。 多分拡張は簡単ですが、一旦考えないことにします。

# 足したい時間 MM:SS 形式
time_list = [
    '3:14',
    '10:35',
    '5:25',
]

次のこれです。 map 関数を使って下から2行目で 'MM:SS' の形式をタプル (MM, SS) に変換しています。 やけくそ感が凄いですね。

# (MM, SS) の tuple にして足していく
tmp_result = reduce(
    lambda x, y: (x[0] + y[0], x[1] + y[1]),
    map(lambda x: (int(x.split(':')[0]), int(x.split(':')[1])), time_list)
)

もし map 関数の結果をリストに変換した場合は [(3, 14), (10, 35), (5, 25)] という結果が得られます。 それをさらに reduce 関数で MM 同士、 SS 同士を足し上げています。

最後の処理です。tmp_result[1] は SS (秒)の合算です。これを 60 で割った時の商と余りを divmod() 関数で取得しています。

>>> divmod(74, 60)
(1, 14) # こんな感じ

その上で tmp_result[0]は MM (分)の合算なので、先ほど計算した商( minute )も足した上で同様に divmod() します。

今の例で言えば tmp_result(18, 74) となります。意味はそのままで 18 分 74 秒です。 最初に 74 を 60 で割り、余り の 14 が秒数、商の 1 を 18 に加えた 19 を 60 で割った余りである 19 が分となります。

# 繰り上がりをいい感じに処理して HH:MM:SS 形式にする
minute, second = divmod(tmp_result[1], 60)
hour, minute = divmod(tmp_result[0] + minute, 60)
result = f'{hour}:{minute}:{second}'

もっと圧縮できるような気がするのですが、もう眠いのでしばらくの間はこれを使います。