Strava/Withings Web API開発 - Pythonリファレンス(日付・時刻処理:datetime)
日付/時刻処理(datetime)
日付や時刻は表記方法のバリエーションなどいろいろ考慮が必要なので以下に整理しました。
(参考リンク)
datetime --- 基本的な日付型および時間型
https://docs.python.org/ja/3/library/datetime.html
Pythonで現在時刻・日付・日時を取得
https://note.nkmk.me/python-datetime-now-today/
Pythonの文字列フォーマット(formatメソッドの使い方)
https://gammasoft.jp/blog/python-string-format/
Pythonのdatetimeで日付や時間と文字列を変換(strftime, strptime)
https://note.nkmk.me/python-datetime-usage/
日時処理(基本)
最初にdatetime(日付/時刻処理のライブラリ)をimportします。あと日付の加算減算を行うためrelativeldeltaをimportしました。
import datetime
from dateutil.relativedelta import relativedelta
現時点の時刻取得や置換、timestamp(unixtime)へのフォーマット変換は以下の通りです。
##現時点の日時取得 (yyyy-mm-dd hh:mm:ss.SSSSSSS)
dt_now = datetime.datetime.now()
##日時を置換 (2020-05-20 12:34:56.123456に置換)
dt_rep = dt_now.replace(year=2020,month=5,day=20,hour=12,minute=34,second=56,microsecond=123456)
##日時->unixtimeへの変換 (2020-05-20 12:34:56.123456 -> 1589945696)
dt_rep_timestamp = dt_rep.timestamp()
##unixtime->日時への変換 (1589945696 -> 2020-05-20 12:34:56.123456)
dt_rep_localtime = datetime.datetime.fromtimestamp(dt_rep_timestamp)
##一部抽出 (2020-05-20 12:34:56.123456 -> 2020/05/20 (Wed.))
dt_rep_yyyymmdd_dow = "{0:0>4d}/{1:0>2d}/{2:0>2d} ({3}.)".format(dt_rep.year, dt_rep.month, dt_rep.day, dt_rep.strftime("%a"))
##一部抽出 (2020-05-20 12:34:56.123456 -> 12:34:56)
dt_rep_hhmmss = "{0:0>2d}:{1:0>2d}:{2:0>2d}".format(dt_rep.hour, dt_rep.minute, dt_rep.second)
主な関数は以下の通りです。
datetime.now()
現在のローカルな日時を返します。
datetime.replace(引数: year=xxxx,month=xx,... )
引数で指定したパラメータを置換します。
(year,month,day,hour,minute,second,microsecondなど)
datetime.timestamp()
日時をタイムスタンプ(unixtime)に変換します。
datetime.fromtimestamp(引数 : timestamp)
タイムスタンプ(unixtime)を日時に変換します。
format(フォーマット出力)
format関数は日時処理ではありませんが、表記をカスタマイズしたい際に使用します。右から左に代入する形で使用します。
print("{0}さんの身長は{1}cmです。".format("サノアツ", 170))
サノアツさんの身長は170cmです。
dt_rep_yyyymmdd_dow = "{0:0>4d}/{1:0>2d}/{2:0>2d} ({3}.)"
.format(dt_rep.year, dt_rep.month, dt_rep.day, dt_rep.strftime("%a"))
-> 2020/05/20 (Wed.)
dt_rep_hhmmss = "{0:0>2d}:{1:0>2d}:{2:0>2d}"
.format(dt_rep.hour, dt_rep.minute, dt_rep.second)
-> 12:34:56
#右側の引数を左側に{0},{1}...の順番で代入します。
#下側の例は{0:0>4d}となっていますが、:(コロン)より右側は書式を表し、0>4dは①最小4桁の幅を設定②右寄せ③整数④スペースがあればゼロで埋める、という意味になります。
datetime.strftime(引数 : %Y, %m, %d, %a など)
指定された引数に従い文字列を返します
%Y 西暦4ケタ, %m 月2ケタ, %d 日2ケタ, %a 曜日(短縮) など
Stravaのデータ加工
今月の走行距離の推移、先月の走行距離の推移をグラフ化する必要があるので、現時点の日時をもとに、今月の月初、先月の月初を変数としてセットする必要があります。
例えば今日が5月20日なら、今月の月初は5月1日0時0分0秒、先月の月初は4月1日0時0分0秒となります。
##replaceで現時点の日時を月初に置き換え
##2020-05-20 18:07:55.154371 -> 2020-05-01 00:00:00
dt_1day = dt_now.replace(day=1,hour=0,minute=0,second=0,microsecond=0)
##relativeldeltaで1か月減算
##2020-05-01 00:00:00 -> 2020-04-01 00:00:00
dt_pm1day = dt_1day + relativedelta(months=-1)
##timedelta, timezone, astimezoneを用いてタイムゾーン形式に変換
##2020-05-01 00:00:00 -> 2020-05-01 00:00:00+09:00
tdelta = datetime.timedelta(hours=+9) ##9:00:00
tzone = datetime.timezone(tdelta) ##UTC+09:00
dt_1day_tz = dt_1day.astimezone(tzone) ##2020-05-01 00:00:00+09:00
replaceでday=1、minute以下をゼロにすることで、月初の日時をセットしています。また1か月減算のため、relativedeltaを用いています。
relativedelta(引数: month=xx など)
引数の設定に応じて時刻の加算減算を行います。
(例)month=-1で1ヶ月減算
参照URL: relativedelta
https://dateutil.readthedocs.io/en/latest/relativedelta.html#
また、タイムゾーンの設定が必要な場合、以下の関数を使用します。
datetime.timedelta(引数: hours=+9 など) #9:00:00
時間差をマイクロ秒精度で表す経過時間値です。
datetime.timezone(引数: オフセット値) #UTC+09:00
UTC からのオフセットとして表します。
datetime.astimezone #2020-05-01 00:00:00+09:00
timezoneの属性を持つ datetime オブジェクトを返します。
(参考:ソースコード)
import datetime
from dateutil.relativedelta import relativedelta
########### 基本的な日時処理 ###########
##①現時点の日時取得 datetime.datetime.now()
dt_now = datetime.datetime.now() ##yyyy-mm-dd hh:mm:ss.SSSSSSS
##②日時を置換 ①.replace()
dt_rep = dt_now.replace(year=2020,month=5,day=20,hour=12,minute=34,second=56,microsecond=123456) ##2020-05-20 12:34:56.123456"
##③日時->unixtimeへの変換 ②.timestamp()
dt_rep_timestamp = dt_rep.timestamp() ##1589945696
##④unixtime->日時への変換(ローカルタイム) fromtimestamp(③) UTCへ変換はutcfromtimestampを使用
dt_rep_localtime = datetime.datetime.fromtimestamp(dt_rep_timestamp) ## 2020-05-20 12:34:56
##⑤一部抽出 {0:0>4d}/{1:0>2d}/{2:0>2d} ({3}.).format(.....)
dt_rep_yyyymmdd_dow = "{0:0>4d}/{1:0>2d}/{2:0>2d} ({3}.)".format(dt_rep.year, dt_rep.month, dt_rep.day, dt_rep.strftime("%a")) ##2020/05/20 (Wed.)
##⑥一部抽出 {0:0>2d}:{1:0>2d}:{2:0>2d}.format(.....)
dt_rep_hhmmss = "{0:0>2d}:{1:0>2d}:{2:0>2d}".format(dt_rep.hour, dt_rep.minute, dt_rep.second) ##12:34:56
print("")
print("########### 基本的な日時処理 ###########")
print("")
print("①現時点の日時取得 datetime.datetime.now() => " + str(dt_now)) ##yyyy-mm-dd hh:mm:ss.SSSSSSS
print("②日時を置換 ①.replace() => " + str(dt_rep)) ##2020-05-20 12:34:56.123456
print("③日時->unixtimeへの変換 ②.timestamp() => " + str(dt_rep_timestamp)) ##1589945696
print("④unixtime->日時への変換 fromtimestamp(③) => " + str(dt_rep_localtime)) ## 2020-05-20 12:34:56
print("⑤一部抽出 {0:0>4d}/{1:0>2d}/{2:0>2d} ({3}.).format() => " + dt_rep_yyyymmdd_dow) ##2020/05/20 (Wed.)
print("⑥一部抽出 {0:0>2d}:{1:0>2d}:{2:0>2d}.format() => " + dt_rep_hhmmss) ##12:34:56
########### Stravaのデータ加工で使用 ###########
## 今月の走行距離の推移、先月の走行距離の推移をグラフ化するため、
## 現時点の日時をもとに、今月の月初、先月の月初の日時を設定。
## 例えば今日が5月20日なら、今月の月初は5月1日、先月の月初は4月1日。
##replaceで現時点の日時を月初に置き換え
dt_1day = dt_now.replace(day=1,hour=0,minute=0,second=0,microsecond=0) ##2020-05-20 18:07:55.154371 -> 2020-05-01 00:00:00.000000
print("")
print("########### Stravaのデータ加工で使用 ###########")
print("")
print("①月初の日時に置き換え replace(day=1に変更) => " + str(dt_1day)) ##2020-05-01 00:00:00
print("②置換え後の月 ①.month => " + str(dt_1day.month)) ##5
print("③置換え後の日付 ①.day => " + str(dt_1day.day)) ##1
print("④タイムスタンプ ①.timestamp() => " + str(dt_1day.timestamp())) ##1588258800.0
print("")
##
##relativeldeltaで1か月減算
dt_pm1day = dt_1day + relativedelta(months=-1) #2020-05-01 00:00:00.000000 -> 2020-04-01 00:00:00.000000
##
print("⑤1か月前 first_date+relativedelta(months=-1) => " + str(dt_pm1day)) ##2020-04-01 00:00:00
print("⑥月 ⑤.month => " + str(dt_pm1day.month)) ##4
print("⑦日 ⑤.day => " + str(dt_pm1day.day)) ##1
print("⑧タイムスタンプ ⑤.timestamp() => " + str(dt_pm1day.timestamp())) ##1585666800.0
print("")
##
##timedelta, timezone, astimezoneを用いてタイムゾーン形式に変換
tdelta = datetime.timedelta(hours=+9) ##9:00:00
tzone = datetime.timezone(tdelta) ##UTC+09:00
dt_1day_tz = dt_1day.astimezone(tzone) ##2020-05-01 00:00:00+09:00
##
##
print("⑨9時間の時差 datetime.timedelta(hours=+9) => " + str(tdelta)) ##9:00:00
print("⑩9時間の時差をTZ形式に datetime.timezone(⑨) => " + str(tzone)) ##UTC+09:00
print("⑪日付時刻をTZ形式に astimezone(⑩) => " + str(dt_1day.astimezone(tzone))) ##2020-05-01 00:00:00+09:00