Pythonで秒数と分・時間・日数を相互に変換
秒数と分・時間・日数との換算は単純な計算でできるが、Pythonではdatetimeモジュールのtimedelta
型を利用するとより簡単に処理できる。
ここでは以下の内容について説明する。
timedelta
オブジェクトの基本- 分・時間・日数などを秒数に変換
- 秒数を分・時間・日数などに変換
datetimeモジュールの基本的な内容については以下の記事を参照。
timedeltaオブジェクトの基本
timedelta
型のオブジェクトはコンストラクタに日数や時間、秒数などを指定して生成する。
指定できる引数はweeks
, days
, hours
, minutes
, seconds
, milliseconds
(ミリ秒), microseconds
(マイクロ秒)。省略すると0
となる。月と年は日数が固定ではないので指定できない。
import datetime
td = datetime.timedelta(weeks=1, days=1, hours=1, minutes=1,
seconds=1, milliseconds=1, microseconds=1)
print(td)
# 8 days, 1:01:01.001001
print(type(td))
# <class 'datetime.timedelta'>
それぞれの引数は浮動小数点数float
やマイナスの値でもOK。hours
に24
以上の値を指定したり、minutes
やseconds
に60
以上の値を指定したりすることも可能。正しく換算される。
以下の例では0.5日(=12時間)と-6時間と120分(=2時間)が合計されて8時間という結果になっている。
print(datetime.timedelta(days=0.5, hours=-6, minutes=120))
# 8:00:00
なお、コンストラクタではなくdatetime
オブジェクトやdate
オブジェクトの引き算でもtimedelta
オブジェクトは生成される。
timedelta
オブジェクトが内部に保持しているのは引数で指定された週や時間の値から換算された日数、秒数、マイクロ秒数のみ。それぞれ属性days
, seconds
, microseconds
でアクセスできる。すべて整数int
。
td = datetime.timedelta(weeks=1, days=1, hours=1, minutes=1,
seconds=1, milliseconds=1, microseconds=1)
print(td)
# 8 days, 1:01:01.001001
print(type(td))
# <class 'datetime.timedelta'>
print(td.days)
# 8
print(type(td.days))
# <class 'int'>
print(td.seconds)
# 3661
print(type(td.seconds))
# <class 'int'>
print(td.microseconds)
# 1001
print(type(td.microseconds))
# <class 'int'>
トータル時間を秒数で表すメソッドtotal_seconds()
もある。属性ではなくメソッドなので()
が必要。返り値は浮動小数点数float
。
print(td.total_seconds())
# 694861.001001
print(type(td.total_seconds()))
# <class 'float'>
トータルの秒数は属性days
, seconds
, microseconds
から算出した値と等しい。
print(td.days * 24 * 60 * 60 + td.seconds + td.microseconds / 1000000)
# 694861.001001
timedelta
オブジェクトから分・時間などを取得したい場合については後述。
なお、これまでのサンプルコードでもあるようにtimedelta
オブジェクトをprint()
で出力すると8 days, 1:01:01.001001
のように日数と時間・分・秒・マイクロ秒が表示される。timedelta
オブジェクトをstr()
で文字列に変換すると、同様の文字列が得られる。
s = str(td)
print(s)
# 8 days, 1:01:01.001001
print(type(s))
# <class 'str'>
分・時間・日数などを秒数に変換
分・時間・日数などから秒数を算出したい場合は、コンストラクタでtimedelta
オブジェクトを生成してからtotal_seconds()
メソッドを使うのが簡単。上述のようにfloat
が返される。
td = datetime.timedelta(days=1, hours=1, milliseconds=100)
sec = td.total_seconds()
print(sec)
# 90000.1
print(type(sec))
# <class 'float'>
まとめて書いてもOK。
sec = datetime.timedelta(days=1, hours=1, milliseconds=100).total_seconds()
print(sec)
# 90000.1
秒数を分・時間・日数などに変換
秒数を分・時間・日数などを使って表したい場合も一旦timedelta
オブジェクトに変換すると簡単。
timedelta
のコンストラクタの引数seconds
に秒数を指定する。60
以上の値や小数点以下を含む値の秒数でも正しく換算される。print()
での出力結果を文字列として取得するだけであればstr()
で変換すればよい。
td = datetime.timedelta(seconds=123456.789)
print(td)
# 1 day, 10:17:36.789000
s = str(td)
print(s)
# 1 day, 10:17:36.789000
print(type(s))
# <class 'str'>
上述のように、timedelta
オブジェクト属性として得られるのはdays
, seconds
, microseconds
のみ。
print(td.days)
# 1
print(td.seconds)
# 37056
print(td.microseconds)
# 789000
秒数から分・時間および残りの秒数を算出して整数int
で取得したい場合、例えば以下のような関数が考えられる。
def get_h_m_s(td):
m, s = divmod(td.seconds, 60)
h, m = divmod(m, 60)
return h, m, s
timedelta
型の__str__()
を参考にした。
divmod()
については以下の記事を参照。
返り値はタプル。アンパックしてそれぞれの変数に格納できる。
- 関連記事: Pythonの関数で複数の戻り値を返す方法
print(get_h_m_s(td))
# (10, 17, 36)
print(type(get_h_m_s(td)))
# <class 'tuple'>
h, m, s = get_h_m_s(td)
print(h)
# 10
print(m)
# 17
print(s)
# 36
トータルの秒数から日・時間・分・秒・マイクロ秒に変換する関数としては以下のような関数が考えられる。上の関数と同じく返り値はタプル。
def get_d_h_m_s_us(sec):
td = datetime.timedelta(seconds=sec)
m, s = divmod(td.seconds, 60)
h, m = divmod(m, 60)
return td.days, h, m, s, td.microseconds
print(get_d_h_m_s_us(123456.789))
# (1, 10, 17, 36, 789000)
print(get_d_h_m_s_us(123.456789))
# (0, 0, 2, 3, 456789)
負の秒数の場合
負の秒数の場合は注意が必要。
トータルの秒数が負のtimedelta
オブジェクトは、以下のように日数days
が負で秒数seconds
とマイクロ秒数microseconds
が正になる。
td_m = datetime.timedelta(seconds=-123456.789)
print(td_m)
# -2 days, 13:42:23.211000
print(td_m.days)
# -2
print(td_m.seconds)
# 49343
print(td_m.microseconds)
# 211000
print(td_m.total_seconds())
# -123456.789
上で定義した関数もそれに準じた値を返す。
print(get_h_m_s(td_m))
# (13, 42, 23)
print(get_d_h_m_s_us(-123456.789))
# (-2, 13, 42, 23, 211000)
絶対値を算出する組み込み関数abs()
はtimedelta
オブジェクトに対しても効くので、期間(幅)として換算したい場合はabs()
を使えばOK。
print(abs(td_m))
# 1 day, 10:17:36.789000
print(get_h_m_s(abs(td_m)))
# (10, 17, 36)
print(get_d_h_m_s_us(abs(-123456.789)))
# (1, 10, 17, 36, 789000)