見出し画像

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

よろしければサポートお願いします。