2000年1月1日午前0時を起点とするTIME関数

 投稿者:nagram  投稿日:2015年 6月29日(月)09時36分59秒
  十進BASICの組込み関数TIMEはその日の午前0時を起点としているため、2つの時刻の差を知りたいとき午前0時をまたぐと正しい値が得られません。
2000年1月1日午前0時を起点とする経過秒数が得られる関数TIME2000を作りました。実行中に日や年が替わっても問題ありません。この関数はPCの内臓時計が2099年12月31日まで有効です。

DECLARE FUNCTION TIME2000
LET t1=TIME
LET t2=TIME2000
LET t3=TIME
PRINT t1;t2;t3
!
FUNCTION TIME2000  ! 2000年1月1日午前0時からの経過秒数
   LOCAL t,d
   LET t=TIME
   LET d=DATE
   IF t>TIME THEN  ! TIME関数とDATE関数が同期しないときの対策
      LET t=0
      LET d=DATE
   END IF
   LET TIME2000=(INT(d/1000)*365+INT((d/1000-1)/4)+MOD(d,1000))*86400+t
END FUNCTION
END


上の関数TIME2000はうるう秒は考慮していません。うるう秒もカウントすると次のようになります。
モジュールleapsecond内にあるDATA文に日本でのうるう秒実施日を事前に追加しておけば自動的に1秒調整します。1秒削除の場合は負数で指定して下さい。
変数interleapでうるう秒を挿入(削除)する時期を選択できます。
0…うるう秒を考慮しない
1…PCの内臓時計が協定世界時(UTC)の場合、うるう秒実施時刻(2015/6/30 23:59:59終了時)に1秒調整。
2…PCの内臓時計が日本標準時(JST)の場合、うるう秒実施時刻(2015/7/1 8:59:59終了時)に1秒調整。
3…PCの内臓時計が日本標準時(JST)の場合、うるう秒実施日の終了時(2015/7/1 23:59:59終了時)に1秒調整。
ただし、Windowsのタイムサービスはうるう秒に自動対応していないので、うるう秒をまたいで実行する際は、プログラム実行前に手動で内臓時計の更新をし、interleapで指定したうるう秒調整時刻が経過した時点でもう一度更新する必要があります。
参考までに、WindowsがNTPサーバーに接続して自動更新をするのは最後の更新から1週間後です。

DECLARE EXTERNAL FUNCTION leapsecond.TIME2000
DECLARE EXTERNAL NUMERIC leapsecond.interleap
LET interleap=2    !【閏秒処理の時期】0=無視,1=UTC実施時,2=JST実施時,3=JST実施日の終了時
LET t1=TIME
LET t2=TIME2000
LET t3=TIME
PRINT t1;t2;t3
END
!
MODULE leapsecond
PUBLIC FUNCTION TIME2000
PUBLIC NUMERIC interleap
SHARE NUMERIC leapDATE,accum1,accum2
DIM month(12)
DATA 0,31,59,90,120,151,181,212,243,273,304,334  ! 各月初日前日までの累計日数
DATA 060101,090101,120701,150701  ! 新たに閏秒が実施される時はyymmdd形式の実施日(JST)を追加。1秒削除は負数(例 -160101)。
! 2000年以降、日本での閏秒実施日(JST) → '06/1/1,'09/1/1,'12/7/1,'15/7/1 午前8時59分59秒終了時
MAT READ month
LET accum1=0
DO
   READ IF MISSING THEN EXIT DO : leapDATE
   LET accum2=accum1
   LET accum1=accum2+SGN(leapDATE)
LOOP
LET leapDATE=ABS(leapDATE)
LET yy=INT(leapDATE/10000)
LET mm=MOD(INT(leapDATE/100),100)
LET leapDATE=yy*365+INT((yy-1)/4+1)+month(mm)+MOD(leapDATE,100)
IF MOD(yy,4)=0 AND mm>=3 THEN LET leapDATE=leapDATE+1
!
EXTERNAL FUNCTION TIME2000  ! 2000年1月1日午前0時からの経過秒数(閏秒対応)
   LET t=TIME
   LET d=DATE
   IF t>TIME THEN  ! TIME関数とDATE関数が同期しないときの対策
      LET t=0
      LET d=DATE
   END IF
   LET d=INT(d/1000)*365+INT((d/1000-1)/4+1)+MOD(d,1000)
   IF interleap>0 THEN  ! interleap=閏秒処理の時期  0=無視,1=UTC実施時,2=JST実施時,3=JST実施日の終了時
      IF d>leapDATE OR d=leapDATE AND (interleap=1 OR interleap=2 AND t>=32400) THEN  ! t=32400→09:00:00
         LET t=t+accum1
      ELSE
         LET t=t+accum2
      END IF
   END IF
   LET TIME2000=(d-1)*86400+t
END FUNCTION
END MODULE
 

戻る