ミスミメンテbotにカウントダウンを実装した
カウントダウン機能をつけたくなった
ミスミメンテbotは メンテナンスが予告されている間毎日ツイートする仕様。
毎日まったく同じツイートをするのはつまらない。 そこで、カウントダウン機能をつけることにした。
#ミスミメンテ
— ミスミメンテおしらせbot《非公式》 (@misumi_mainte) 2020年1月23日
Start: 1/26 11:00
Goal: 1/27 7:30
メンテまであと 2日と4時間
https://t.co/C2VY3rgPcZ
#ミスミ pic.twitter.com/8BQiSVAp3k
実装
以下のようなカウントダウンの関数を作った。
いままでのプログラムではツイートしかしなかった為、 ミスミサイトから取得した日時を数字に変換せず文字列として扱っていた。 また、開始終了の日時をまとめて使いやすくする為、配列に格納している。
そこで、ひとまず文字列の配列として日時を受け取り、関数内で数字への変換機能を実装することにした。
# countdownを文字列で返す # 入力は文字列の配列 def count_down(date, time):
メンテ日時の文字列を数字に変換
先述したように、今までは日時を文字列として扱っていた。
今回は残り日時の計算に使いたいので、数字に変換する。
# 取得日時を切り出してintにする str = re.sub(r'\D', ' ', date[0]) sdate = str.split() smonth = int(sdate[0]) # 月 sday = int(sdate[1]) # 日 str = re.sub(r'\D', ' ', time[0]) stime = str.split() shour = int(stime[0]) # 時
現在日時の取得
現在日時はpythonの機能で取得できる。
気をつけなければいけないのはタイムゾーン。
ミスミサイトの表示はJST。 筆者は日本に住んでいて、JST設定のPCを使っている。 そのため、ローカルで日時差分をとると何も考えなくても問題なく動く。
しかし、定期実行に使っているherokuはデフォルトでJSTではない為、 明示的にタイムゾーンをJSTに指定する必要がある。
# 現在日時 # タイムゾーンの生成 JST = timezone(timedelta(hours=+9), 'JST') # JSTで現在時刻 time_info=datetime.now(JST) # time_info=datetime.today() print('time_info:{}'.format(time_info)) year_now = time_info.year
メンテ日時を現在日時と同じ形式に整える
ところで、ミスミサイトのメンテ日時案内には年が表示されたりされなかったりする。 また、ツイート本文に年をわざわざ書く必要も感じない。
このため、スクレイピングでは年情報を取得していない。
しかし、 datetimeオブジェクトを使いたいので、 メンテ日時にも年情報が必要となる。
datetime --- 基本的な日付型および時間型 — Python 3.8.1 ドキュメント
メンテナンスが年末年始に行われることはないだろうと考え、 現在の年=メンテ時の年 と指定する。
前章で用意した、
year_now = time_info.year
を利用する。
# 開始日時 # メンテは年をまたがないと仮定 # time_start = datetime(year_now,1,2,3) time_start = datetime(year_now,smonth,sday,shour, tzinfo=JST) print('time_start:{}'.format(time_start))
フォーマッティングして文字列として返す
引き算で差分を計算。
秒で出るので時間に変換。
フォーマットを使うときれいな表示になる。
# 差分 time_diff = time_start-time_info # 文字列を返す cd_s = "{0}日と{1}時間".format(time_diff.days, time_diff.seconds // 3600)
作成したコード
参考文献
django - How do I convert datetime.timedelta to minutes, hours in Python? - Stack Overflow