質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

648閲覧

Pythonの時間を取り扱う関数にて30時などの各桁の上限を超える時刻を1発で出せる関数はあるか?

Kazumori102

総合スコア45

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/08/05 08:09

編集2020/08/05 09:15

前提・実現したいこと

datetime型では普通の場合は、30時などと出力しようとすると、(1日と)6時間になってしまう。
これを普通に30時と出力できる関数は自作する以外にはないのか?
内部ではdatetime(day=1,hour=6)で、出力するときには30時と表せるとよいという事である。

同様に80分や、70秒などと、表せるとよい。そういうものはないだろうか?

試したこと

自作はした。時間を分に崩す版である。

pyhton

1from dateutil.parser import parse as dt_parse 2import datetime as dt 3time = "2:08:32" 4index_time = dt_parse(time) 5index_time = index_time + dt.timedelta(microseconds=330) 6print(index_time.strftime("%H:%M:%S:%f")) 7 8super_minit = 60* int( index_time.strftime("%H") ) + int( index_time.strftime("%M") ) 9 10rounded_mili_sec = round(int(index_time.strftime("%f") )/100.0) 11 12 13print( f"{super_minit:02}:{index_time.strftime('%S')}:{rounded_mili_sec:02}" ) 14#128:32:03

余談であるが、dateutil.parserは「カンマ区切りのミリorマイクロ秒」及び、「各桁の上限を超える時刻」に対応していないようだ。
これに対処する汎用的解法をご教授願えないだろうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aokikenichi

2020/08/05 09:05

単に文字列として30時、80分、70秒では駄目なのでしょうか?
Kazumori102

2020/08/05 09:14 編集

datetime型でないとダメです
Kazumori102

2020/08/05 09:14

暗黙でした。以後明記します。
Penpen7

2020/08/15 09:35

現在は、どういう回答を求められているのでしょうか? 解決されたのであれば、現在の回答をベストアンサーとして、この質問をクローズしてください。
guest

回答1

0

ベストアンサー

少なくとも標準的なものではありませんので、自分で作るのが良いと思います。汎用的な方法として

  • 最大となる時間単位(時間、分、秒)を指定する

のが良いと思います。私が実装するとしたら、下記のようになるでしょうか。parseという外部パッケージを用いていますがMyTime.parse()を使わないのであれば不要です。

python

1from datetime import datetime, timedelta 2from string import Formatter 3import parse 4 5 6class MyTime: 7 epoch = datetime.strptime("00:00:00", "%H:%M:%S") 8 9 @classmethod 10 def format(cls, time: datetime, format: str, max_unit: str = "D") -> str: 11 dt = time - cls.epoch 12 remainder = dt.total_seconds() 13 units = {"W": 604800, "D": 86400, "H": 3600, "M": 60} 14 process_flag = False 15 values = {} 16 for unit, seconds in units.items(): 17 if unit == max_unit: 18 process_flag = True 19 if process_flag: 20 values[unit], remainder = divmod(remainder, seconds) 21 values = {k: int(v) for k, v in values.items()} 22 values["S"] = remainder 23 return Formatter().format(format, **values) 24 25 @classmethod 26 def parse(cls, time_string: str, format: str) -> datetime: 27 units = {"W": 604800, "D": 86400, "H": 3600, "M": 60, "S": 1} 28 parsed = parse.parse(format, time_string) 29 total_seconds = 0.0 30 for unit, seconds in units.items(): 31 if unit in parsed: 32 total_seconds += float(parsed[unit]) * seconds 33 return cls.epoch + timedelta(seconds=total_seconds)

使い方は次の通りです。

python

1# datetime型を準備 2# strptimeを使うとマイクロ秒までパース可能だが年月日を省略すると1900-01-01が基準となる 3# 結果: 1900-01-01 02:08:32.000330 4time = "2:08:32.000330" 5t = datetime.strptime(time, "%H:%M:%S.%f") 6print(t) 7 8# シンプルな例 9# 結果: 0 days 2:8:32.00032999999985 10print(MyTime.format(t, "{D} days {H}:{M}:{S}")) 11 12# 時間、分、秒の桁を2桁にし、秒はマイクロ秒まで表示 13# 結果: 0 days 02:08:32.000330 14print(MyTime.format(t, "{D} days {H:02d}:{M:02d}:{S:09.6f}")) 15 16# 時間、分、秒の桁を2桁にし、秒はマイクロ秒まで表示、ただし最大の桁は時間とする 17# 結果: 02:08:32.000330 18print(MyTime.format(t, "{H:02d}:{M:02d}:{S:09.6f}", max_unit="H")) 19 20# 分、秒の桁を2桁にし、秒はマイクロ秒まで表示、ただし最大の桁は分とする 21# 結果: 128:32.000330 22print(MyTime.format(t, "{M:02d}:{S:09.6f}", max_unit="M")) 23 24# 最大の桁を秒とする 25# 結果: 7712.00033 26print(MyTime.format(t, "{S}", max_unit="S")) 27 28# 時間が24時間を超える場合のパース 29# 結果: 1900-01-01 02:08:32.000330 30time = "128:32.000330" 31t = MyTime.parse(time, "{M}:{S}") 32print(t)

投稿2020/08/05 21:25

yymmt

総合スコア1615

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kazumori102

2020/08/11 18:56

多忙につきお返事遅れてすみません。コード例まことにありがとうございます。 いただいたコードのフォーマットにミリ秒を追加する場合は、 unitsに "mS":0.001 としておけばいい塩梅でしょうか?
yymmt

2020/08/12 03:58 編集

unitsに"S": 1, "MS":0.001を追加して、かつvalues["S"] = remainderの箇所を values["US"] = remainder / 1e-6 とする必要があります。最後はどうしても余りが出るためこの処理が必要です。
yymmt

2020/08/12 03:55

少し説明を追記しますと「表現可能な最小単位をどこにするか」を暗黙に設定しています。最後のvalues[最小単位] = remainderでは全ての余りを最小単位として押し付けています。元のソースコードでは最小単位を秒とし、上記のコメントの例では最小単位をマイクロ秒としています。
Kazumori102

2020/08/12 04:42

なるほど。今の頭だとわからん。ありがとうございます。 頭がいい感じになったらじっくり考えてみます。ご丁寧にどうも。
Kazumori102

2020/08/16 10:16

無事理解して実装できました。BAとさせて頂きます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問