2017年9月11日月曜日

Luaで日時の計算

 Luaではos.timeで数値を取り出すことができ、os.dateで数値から人間が扱いやすい数字(グレゴリオ暦)に変換する。また、os.timeにグレゴリオ暦のテーブルを渡すと、数値が帰る。

function printDate(d)
 print(d.year .. "/" .. d.month .. "/" .. d.day .. " " .. d.hour .. ":" .. d.min .. ":" .. d.sec)
end

t = 1234567890
d = os.date("*t", t)
printDate(d)

d = {
 year = 2001,
 month = 9,
 day = 9,
 hour = 1,
 min = 46,
 sec = 40,
}
t = os.time(d) + 9 * 60 * 60
print(t)

 このスクリプトは
2009/2/14 8:31:30
1000000000
のようになる。
 一見、UNIX時間のようだが、これは環境依存のようだ。

 Lua言語のライブラリ関数#os.timeによると、「os.timeの戻り値は、os.dateおよびos.difftimeの引数としてのみ、意味を持ちます」と書いてあり、os.dateとos.difftime以外には使えないことが示唆されている。
 公式のマニュアルにも、似たようなことが書いてある。
 マニュアルによると「In POSIX, Windows, and some other systems, this number counts the number of seconds since some given start time (the "epoch")」(POSIX、Windows、およびその他のシステムでは、この番号は、指定された開始時刻(「エポック」)からの秒数をカウントします)ということで、とりあえずはUNIX時間として扱っちゃって大丈夫だと思う。

 マイコンで上記1234567890を文字列にすると"2009/2/13 23:31:30"という風になる。上記の結果とは異なるが、マイコンはUTC+0で実行され、PCはUTC+9で実行されたことによる違い。

 マイコンで日時を返すには、"int _gettimeofday(struct timeval *tv, struct timezone *tz)"を実装すればいい。今回試した限りでは、tzはnullが指定されていた。
 Luaはgmtimeとlocaltimeを使うらしいので、タイムゾーンの決定はCライブラリ側で行われているっぽい。Cのタイムゾーンは変更できるらしいのだが、ちょろっと調べても方法がわからなかった。

 日時の処理はかなり泥沼な感じなので、できれば近寄らずにいたい。

 とりあえず、Luaで日時を扱うなら、os.timeでsecに変換して、操作して、os.dateで日時に戻して、という感じで扱えそう(環境依存)。


 マイコンのLuaで時間を扱いたいけど、RTCのバックアップ電池を実装するスペースがない。有ってもコイン電池ケースなんて持ってないからできないんだが。
 せっかくSTM32F4のRTCは人間に扱いやすいようになってるのにね。って、それだとUNIX時間に変換したりしなきゃいけないから面倒なんだ。こうなると、STM32F1の32bitカウンタのほうが便利な気がするなぁ。
 マイコンのRTCモジュール、64bitカウンタとかで、通常動作時はMHzを分周して、スリープ時は32.768kHzの水晶で、みたいな機能になって欲しい。あと外部の1PPSで水晶を補正する機能とか欲しい。

0 件のコメント:

コメントを投稿