NScripterでepoch秒を扱ってみる。
epoch秒と言うのは、UNIX文化圏で使われているもので、グリニッジ標準時間1970年1月1日00:00:00からの経過秒数のことです。PerlでCGIとかやってれば、日付や時間を取り扱うのに避けては通れない概念な訳です。
これ、あったらあったでかなり楽になります。たとえば、ある日から別のある日まで何日経過したのかなどを計算するのに使えます。両方の日付のepoch秒を出して、その差を24*60*60で割れば日数になるからです。他にも、時間を記録したいが人間がぱっと見気付かない、あるいは調査させる気をなくさせる目的で、epoch秒を使うこともあります。
まあ、そんなのもコミで、色々NScripter用に色々追加してみたりします。
追加命令
年月日の年は、NScripterフォーマット、つまり、西暦2000年を0とした数値を使います。
- now2epoch
- 現在年月日時分秒をepoch秒に変換
- date2epoch
- 年月日時分秒を与えてecpoch秒に変換
- epoch2date
- 逆にepoch秒を年月日時分秒に変換
- is_leapyear
- 年(このコマンドだけ西暦)を与えると、それが閏年かどうか判定する。
- date2weekday
- 年月日を与えると、その曜日を返す。0が日曜日、6が土曜日
- date2day_of_year
- 年月日を与えると、その日がその年の何日目かを返す。1月1日が1、12月31日が365 or 366
注意点
閏年判定はきちんとしてる(はず)ので、未来の日付を使うこともできます。
しかしその性質上、マイナスのepoch秒は扱えません。1970年以前の日付は表現できないことになります。
使い道
ちょっと考えてみましたが、実際の暦をゲームに導入するのに、epoch秒は使えるかも知れません。
また、時限付btn系命令を使う場合、resettimer等を使ってしまうので、NScripterが起動してからの秒数を破壊してしまうことがあるでしょう。その場合、*start節の早いうちにepoch秒を取得しておき、現在epoch秒と比較することで、NScripter起動時からの秒数を取得できます。ミリ秒でないのはご勘弁を。
define節game以上
mov %0,100 ; 環境に合わせてお好みで numalias time_year,%0:inc %0 numalias time_month,%0:inc %0 numalias time_day,%0:inc %0 numalias time_hour,%0:inc %0 numalias time_min,%0:inc %0 numalias time_sec,%0:inc %0 numalias time_loop,%0:inc %0 numalias time_leap,%0:inc %0 numalias time_epoch,%0:inc %0 numalias is_leap_result,%0:inc %0 numalias is_leap_year,%0:inc %0 defsub now2epoch defsub date2epoch defsub epoch2date defsub is_leapyear defsub date2weekday defsub date2day_of_year
game以下start節前
;================== ; date2weekday ;================== ; 年月日から曜日を計算する。 ; 第一引数:結果を受け取る数値変数。0〜6が日曜日から土曜日に対応 ; 第二引数〜第三引数:年月日の数値。NScripterフォーマット ; zellerの公式ばんざーい *date2weekday getparam i%time_epoch,%time_year,%time_month,%time_day add %time_year,2000 if %time_month<3 add %time_month,12:dec %time_year mov %%time_epoch,(%time_year+%time_year/4-%time_year/100+%time_year/400+(13*%time_month+8)/5+%time_day) mod 7 return ;================== ; date2day_of_year ;================== ; ある年月日がその年の何日目かを返す。 ; 第一引数:結果を受け取る数値変数。0〜6が日曜日から土曜日に対応 ; 第二引数〜第三引数:年月日の数値。NScripterフォーマット ; 1月1日は1に、12月31日は365 or 366になる。 *date2day_of_year getparam i%time_epoch,%time_year,%time_month,%time_day add %time_year,2000 is_leapyear %time_leap,%time_year mov %%time_epoch,%time_day ; 下準備 if %time_month=1 return add %%time_epoch,31 if %time_month=2 return add %%time_epoch,28+%time_leap if %time_month=3 return add %%time_epoch,31 if %time_month=4 return add %%time_epoch,30 if %time_month=5 return add %%time_epoch,31 if %time_month=6 return add %%time_epoch,30 if %time_month=7 return add %%time_epoch,31 if %time_month=8 return add %%time_epoch,31 if %time_month=9 return add %%time_epoch,30 if %time_month=10 return add %%time_epoch,31 if %time_month=11 return add %%time_epoch,30 return ;================== ; now2epoch ;================== ; 現在の日付・時刻をエポック秒に変換する。 ; 第一引数:結果を受け取る数値変数 *now2epoch getparam i%time_epoch date %time_year,%time_month,%time_day time %time_hour,%time_min,%time_sec goto *date2epoch_main ;================== ; epoch2date ;================== ; エポック秒をNScripterの日付形式に変換する。 ; 第一引数:変換するエポック秒 ; 第二引数〜第七引数:結果を受け取る数値変数。年・月・日・時・分・秒。 *epoch2date getparam %time_epoch,i%time_year,i%time_month,i%time_day,i%time_hour,i%time_min,i%time_sec add %time_epoch,32400 ; タイムゾーンを東京に設定 mov %%time_day,%time_epoch div %%time_day,24*60*60 ; 日数を計算。 mov %%time_year,1970 ; 年の処理 ~ is_leapyear %time_leap,%%time_year if %%time_day<366+%time_leap jumpf inc %%time_year sub %%time_day,365+%time_leap jumpb ~ sub %%time_year,2000 mov %%time_month,1 ; 月の処理と日の処理 notif %%time_day>31 jumpf ; 一月 sub %%time_day,31:inc %%time_month if %%time_day<29+%time_leap=1 jumpf ; 二月 sub %%time_day,28+%time_leap:inc %%time_month if %%time_day<32 jumpf ; 三月 sub %%time_day,31:inc %%time_month if %%time_day<31 jumpf ; 四月 sub %%time_day,30:inc %%time_month if %%time_day<32 jumpf ; 五月 sub %%time_day,31:inc %%time_month if %%time_day<31 jumpf ; 六月 sub %%time_day,30:inc %%time_month if %%time_day<32 jumpf ; 七月 sub %%time_day,31:inc %%time_month if %%time_day<32 jumpf ; 八月 sub %%time_day,31:inc %%time_month if %%time_day<31 jumpf ; 九月 sub %%time_day,30:inc %%time_month if %%time_day<32 jumpf ; 十月 sub %%time_day,31:inc %%time_month if %%time_day<31 jumpf ; 十一月 sub %%time_day,30:inc %%time_month ; 十二月 ~ inc %%time_day if %%time_day=32 mov %%time_day,1:mov %%time_month,1:inc %%time_year ; 時の処理 mov %%time_sec,%time_epoch mod (24*60*60) mov %%time_hour,0 ~ notif %%time_sec>60*60 jumpf inc %%time_hour sub %%time_sec,60*60 jumpb ~ ; 分、秒の処理 mov %%time_min,0 ~ notif %%time_sec>60 jumpf inc %%time_min sub %%time_sec,60 jumpb ~ return ;================== ; date2epoch ;================== ; 日付をエポック秒(1970年1月1日00:00:00からの経過秒)に変換する。 ; 第一引数:結果を受け取る数値変数 ; 第二引数:年を表す数値。0は西暦2000年を意味する。 ; 第三引数:月を表す数値。1〜12の範囲で。 ; 第四引数〜第七引数:それぞれ日、時、分、秒。 *date2epoch getparam i%time_epoch,%time_year,%time_month,%time_day,%time_hour,%time_min,%time_sec *date2epoch_main mov %%time_epoch,0 ; 年の処理 if %time_year=1970 jumpf for %time_loop=1970 to %time_year+1999 add %%time_epoch,365 is_leapyear %time_leap,%time_loop if 1=%time_leap inc %%time_epoch next ~ ; 月の処理 if %time_month=1 jumpf add %%time_epoch,31 if %time_month=2 jumpf is_leapyear %time_leap,%time_year add %%time_epoch,28+%time_leap if %time_month=3 jumpf add %%time_epoch,31 if %time_month=4 jumpf add %%time_epoch,30 if %time_month=5 jumpf add %%time_epoch,31 if %time_month=6 jumpf add %%time_epoch,30 if %time_month=7 jumpf add %%time_epoch,31 if %time_month=8 jumpf add %%time_epoch,31 if %time_month=9 jumpf add %%time_epoch,30 if %time_month=10 jumpf add %%time_epoch,31 if %time_month=11 jumpf add %%time_epoch,30 ~ add %%time_epoch,%time_day-1 ; 日の処理 mul %%time_epoch,24*60*60 ; 日数を24*60*60倍して秒数に変換 add %%time_epoch,%time_hour*60*60 ; 時の処理 add %%time_epoch,%time_min*60 ; 分の処理 add %%time_epoch,%time_sec ; 秒の処理 sub %%time_epoch,32400 ; タイムゾーンを東京に。 return ;================== ; is_leapyear ;================== ; その年が閏年かどうか調べる。 ; 第一引数:結果を受け取る数値変数。0は通常年。1は閏年 ; 第二引数:年。西暦で指定 *is_leapyear getparam i%is_leap_result,%is_leap_year mov %%is_leap_result,0 if 0=%is_leap_year mod 400 mov %%is_leap_result,1:return if 0=%is_leap_year mod 100 return if 0=%is_leap_year mod 4 mov %%is_leap_result,1:return return