MicroPython的午睡(50) ATOMLite、やらかしTZ、カレンダ変換

Joseph Halfmoon

前回、ATOMLiteで温湿度を測ってサーバーのNode-REDに報告をあげるようにいたしました。測定テストで温湿度の日変化を測るべし、とてATOMLiteを動かしたまま眠りについて発覚しました。アイキャッチ画像を御覧じろ。25時?RTCがそういうこと言う?私のバグでした、トホホ。NTPで得たUTCと、報告用のJSTの変換の間違い。

※「MicroPython的午睡」投稿順 Indexはこちら

前回というか、このところ「継ぎ足しながら」熟成中のスクリプトは、起動時にネットワーク接続した後に、NTPサーバーに接続して時刻を取得、M5ATOMLiteのRTCに時刻を設定するようになっています。NTPサーバーから得られるのはUTC(Universal Time, Coordinated、協定世界時)です。

どうせJSTで運用するつもりなので、RTCに時刻を設定するときにUTCをJSTに変換してから設定すれば今回のような問題は起きなかった、多分。でも面倒なのでUTCのままRTCにブチこんでいました。

    1. RTCに設定する日付時刻はUTCのままでいいんじゃね。
    2. 表示するときにJSTに変換すれば

などという浅はかな考えです。さらにお馬鹿なことに、

とりあえず、当面、JSTに変換するのは時間に9足せばよくね

お気づきの通り、この方法ではうまく行きませぬ。しかし、日本時間で午前9時から夜中の12時の間であれば、なんとなく動いているように見えるのであります。そしてたまたま、M5ATOMLiteのMicroPythonを動かすときに限って毎回そのような時間帯。この問題は完全に忘れてました。

そして温湿度の日変化を測るべく夜中も動かして問題がようやく発覚したという状況。症状は以下のとおり。

    1. 日本時間の夜中の12時を過ぎると0時xx分でなく24時xx分になる。以降25時、26時と時刻が進む。日付は前の日のまま。
    2. 日本時間の午前9時をすぎると「正常」な日付時刻になる

カレンダのことを考えず、TZ=+9で時間にだけ9足すとこんなことになります。念のため、ご本家へのリンクを貼り付けておきます。

JST Clock

またもや「やっつけ」修正

ない頭で考えたら、「汎用」にしようとするとUTCからの変換、結構メンドイです。日本時間は+9時間ですが、西経の地域は遅れる方向だし、閏年も400年ルール?とかあります。とりあえず「やっつけ」、

    • 日本時間、+9以外の対応は不可
    • あと380年くらい閏年の例外はやってこないので無視(2400年までこのスクリプトを動かすなんてことは断じてない!)

そういう条件のもとであれば「やっつけ」で書いた以下のコードでも動くんじゃないかい?(前回コードの問題部分のみ更新)

# FOR JST CONVERSION ONLY
    def currentTIME(self):
        SM = (4, 6, 9, 11)
        t0 = machine.RTC().datetime()
        hour = t0[4]+self.tz
        day = t0[2]
        month = t0[1]
        year = t0[0]
        if hour > 23:
            hour -= 24
        if hour < self.tz:
            if ((day == 31) and (month != 12)) or ((day == 30) and (month in SM)):
                day = 1
                month += 1
            elif ((day == 31) and (month == 12)):
                day = 1
                month = 1
                year += 1
            elif ((day == 29) and (month == 2)) or ((day == 28) and (month == 2) and ((year % 4) != 0)):
                day = 1
                month += 1
            else:
                day += 1
        return "{0}/{1:02d}/{2:02d} {3:02d}:{4:02d}:{5:02d}".format(year,month,day,hour,t0[5],t0[6])
「やっつけ」修正の穴だらけの確認

UTCからJSTへの変換の確認用のコードを書いて、実際にM5ATOMLite上で走らせてみました。でも、ちゃんとカレンダを網羅テストするのは、これまた大変。ありがちな、小の月の月末、大の月の月末、年末、閏年の2月末、閏年じゃない年の2月末をテストするものであります。本当は、もっとちゃんとやらんといかんね。まあ、やっつけ修正の確認なので、勘弁してくだされや。

# TEST RTC Calendar
import machine, time
from LiteNetwork import LiteNetwork

LiteNet = LiteNetwork()

rtc = machine.RTC()

def dut(tpl):
    rtc.datetime(tpl)
    print("-------------------------------")
    for _i in range(3):
        print(LiteNet.currentTIME())
        time.sleep(1)
        

def main():
    dut( (2021, 11, 01, 1, 14, 59, 59, 0) )
    dut( (2021, 11, 01, 1, 23, 59, 59, 0) )
    dut( (2021,  1, 31, 1, 14, 59, 59, 0) )
    dut( (2021,  1, 31, 1, 23, 59, 59, 0) )
    dut( (2020,  2, 28, 1, 14, 59, 59, 0) )
    dut( (2020,  2, 28, 1, 23, 59, 59, 0) )
    dut( (2020,  2, 29, 1, 14, 59, 59, 0) )
    dut( (2020,  2, 29, 1, 23, 59, 59, 0) )
    dut( (2021,  2, 28, 1, 14, 59, 59, 0) )
    dut( (2021,  2, 28, 1, 23, 59, 59, 0) )
    dut( (2021,  4, 30, 1, 14, 59, 59, 0) )
    dut( (2021,  4, 30, 1, 23, 59, 59, 0) )
    dut( (2020, 12, 31, 1, 14, 59, 59, 0) )
    dut( (2020, 12, 31, 1, 23, 59, 59, 0) )

if __name__ == "__main__":
    main()

実際に動かした結果が以下です。とりあえず動いているみたい。

-------------------------------
2021/11/01 23:59:59
2021/11/02 00:00:00
2021/11/02 00:00:01
-------------------------------
2021/11/02 08:59:59
2021/11/02 09:00:00
2021/11/02 09:00:01
-------------------------------
2021/01/31 23:59:59
2021/02/01 00:00:00
2021/02/01 00:00:01
-------------------------------
2021/02/01 08:59:59
2021/02/01 09:00:00
2021/02/01 09:00:01
-------------------------------
2020/02/28 23:59:59
2020/02/29 00:00:00
2020/02/29 00:00:01
-------------------------------
2020/02/29 08:59:59
2020/02/29 09:00:00
2020/02/29 09:00:01
-------------------------------
2020/02/29 23:59:59
2020/03/01 00:00:00
2020/03/01 00:00:01
-------------------------------
2020/03/01 08:59:59
2020/03/01 09:00:00
2020/03/01 09:00:01
-------------------------------
2021/02/28 23:59:59
2021/03/01 00:00:00
2021/03/01 00:00:01
-------------------------------
2021/03/01 08:59:59
2021/03/01 09:00:00
2021/03/01 09:00:01
-------------------------------
2021/04/30 23:59:59
2021/05/01 00:00:00
2021/05/01 00:00:01
-------------------------------
2021/05/01 08:59:59
2021/05/01 09:00:00
2021/05/01 09:00:01
-------------------------------
2020/12/31 23:59:59
2021/01/01 00:00:00
2021/01/01 00:00:01
-------------------------------
2021/01/01 08:59:59
2021/01/01 09:00:00
2021/01/01 09:00:01

グレゴリオ暦、なめたらあかんぜよ。

MicroPython的午睡(49) ATOMLite、温湿度を測ってNode-RED報告 へ戻る

MicroPython的午睡(51) ATOMLite、BMP280の補償計算大変なのね へ進む