note.nkmk.me

Pythonで秒数と分・時間・日数を相互に変換

Date: 2019-02-04 / tags: Python

秒数と分・時間・日数との換算は単純な計算でできるが、Pythonではdatetimeモジュールのtimedelata型を利用するとより簡単に処理できる。

ここでは以下の内容について説明する。

  • timedeltaオブジェクトの基本
  • 分・時間・日数などを秒数に変換
  • 秒数を分・時間・日数などに変換

detetimeモジュールの基本的な内容については以下の記事を参照。

スポンサーリンク

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。hours24以上の値を指定したり、minutesseconds60以上の値を指定したりすることも可能。正しく換算される。

以下の例では0.5日(=12時間)と-6時間と120分(=2時間)が合計されて8時間という結果になっている。

print(datetime.timedelta(days=0.5, hours=-6, minutes=120))
# 8:00:00

なお、コンストラクタではなくdatetimeオブジェクトやdateオブジェクトの引き算でもtimedelataオブジェクトは生成される。

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

timedelataオブジェクトから分・時間などを取得したい場合については後述。

なお、これまでのサンプルコードでもあるように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()については以下の記事を参照。

返り値はタプル。アンパックしてそれぞれの変数に格納できる。

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)
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事