続きです。こちらはしっかり32ビットの壁があります。
----^ DATE2UT.DEF ( date:2010-03-16 time:00:10 ) -----< cut here
= Date2UT.def v0.10 = by H_ear
#if 0
日時をUNIXTIMEに変換
※要高橋版VZ[以降]
32bitの範囲のため上限が2038年程度
但しoverflowを!で告知するため,表示された数値+4294967296と推定可能
#endif
* mad for vz!
1 ^\ "" ?.
i[, p[, q[, o[, y[, m[, d[, l[,
; ---- 日付の取得 ----
:g &m("日時を【YYYY/MM/DD/HH:MM:SS】の形式で入力.(年必須)")
&g("YYYY/MM/DD/HH:MM:SS") &Cr
(r|1+1)??{ ;[ESC]/[CR]のみ
:c &m("! Canceled") >z
}
; ---- バッファの確保と初期化 ----
&> q4+p12+o0=r, ;<o><p><q> buffers
i-, (5){ &Im(o+i,0) i+=4, } ;<i> counter
; ---- 数字列を数値化 ----
i-, #J #e #< ;pw dummy text winow
:l (cd<'0' || cd>'9')?>v ;数字なら取得
&n o..i=r,
i++, #f ;要するに/や:でなくても可
(i<6)?>l ;6回まで取得
:v (s)?#[ ;close #J window
; ---- 不正な年月日をチェック ----
(o..0<1970)?{
&a("年が不正です.再入力します")
(r>0)?>g >c
}
(o..1<1 || o..1>12)?o..1=1, ;月
(o..2<1 || o..2>31)?o..2=1, ;日
y[=o..0, &01 y], ;日の整合性チェック
(o..2>r.o..1)?o..2=r.o..1, ;超えていれば最大値
(o..0==1970 && o..1==1 && o..2==1 && o..3<9)?{
&a("1970/01/01/09:00:00以降のみ. 再入力します")
(r>0)?>g >z
}
; &m("%d/%02d/%02d/%02d:%02d:%02d",o..0,o..1,o..2,o..3,o..4,o..5)
; ---- 日数算出 ----
; 0000/03/00を基準とする日数を算出
; 1月と2月を前年の13月と14月として扱い3月から1年を開始
; 月平均日数定数30.6を使用
; --> *p = 総日数
y[=o..0, m[=o..1, d[=o..2,
&Im(p,0) ;reset p
(m<3)?{ y--, m+=9, }?{ m-=3, } ;仮年月を設定
&Ia(p,y) &Im(p,365) ;年数分の日数
&Ia(p,m*30+(m*6+5)/10+d) ;月平均日数と日を足す
&Ia(p,y/4) ;閏年を足す
&Is(p,y/100) ;百年非閏年を引く
&Ia(p,y/400) ;四百年閏年を足す
d], m], y],
; ---- 1970/01/01以降の日数にして標準時差を調整 ----
; 1970/01/01以降の日数を確定(非汎用定数を使用)
; 1日の秒数86400,標準時差9時間分の秒数32400
; いずれも100未満の端数がないうちに処理を済ませる
; <-- *p = 基準日からの総日数
; *q = 定数(基準日から1970/01/01未満の日数)
; *p -= *q : 1970/01/01以降の日数
; --> *p = 日数分の秒数の100分の1
q..1=$A, q..0=$FA6D, ;719469/65536=10_64109 1970/01/01〜
&Ls(p,q) ;定数(0000〜1969)を引く
&Im(p,864) ;p*86400 :日数分の秒数/100
&Is(p,324) ;地域標準時の差/100を引く
; ---- 日数から秒数へ ----
; overflowを予測して超過するならフラグを立てる
; *pと定数$28F5C28($FFFFFFFF/100)を比較し
; *pが小さい:オーバーフロウしない
; *pが大きい:オーバーフロウする -> largeフラグを立てる
q..1=$28F, q..0=$5C28, ;定数 $28F5C28 * 100 < $FFFFFFFF
&Lc(q,p) ;long比較(※高橋版以降のみ)
l=r<0, ;<l> too large(32bit)フラグ
&Im(p,100) ;フラグが立っていると丸められる
; ---- 時刻を秒数に ----
; 時刻の入力は必須ではないので入力なくば処理省略
; --> *q = 時刻の秒数
(i<4)?>p ;時刻を入力していないなら出力
&Im(q,0)
&Ia(q,o..3) &Im(q,60) ;時->分
&Ia(q,o..4) &Im(q,60) ;分->秒
&Ia(q,o..5) ;秒
; ---- 合計 ----
; 日数分の秒数に時刻分の秒数を加算
; 加算した値よりも小さくなればoverflowと判断できる
; overflowしたらフラグを立てる
&La(p,q) ;時刻分の秒数を足す
&Lc(p,q) l=r<0, ;足した値よりも少なければoverflow
; ---- print [flag] *p o..0〜o..5 ----
;overflowがあれば数値に'!'を前置して示す
:p &m("%c %lu <- %d/%02d/%02d/%02d:%02d:%02d",' '+l,p..0,p..1,o..0,o..1,o..2,o..3,o..4,o..5)
:z ; ---- exit ----
l], d], m], y], o], q], p], i],
&d #] .
00: ; ---- buffer ----
(3+$)."$[20]"
01: ; ---- 日の整合性確認 ---- ;from calendar.def
r=" $(1f,1c,1f,1e,1f,1e,1f,1f,1e,1f,1e,1f,)",
; 1__2__3__4__5__6__7__8__9__a__b__c
(y%4==0 && (y%100!=0 || y%400==0))?r.2=29, ?r.2=28, ;閏年
(r)
*
[Variables]
i counter
p,q long int ptr
o buf word*6 (output)
y,m,d 作業用年月日
l large flag
[Buffers]
pw #g/#J 日付入力/取得
p,q [8]double*2
o [12]word*6
[History]
2010/03/16 0.10 初版
[Notes]
結局,仮想基準日0000/03/00を使った。
----$ DATE2UT.DEF ( lines:131 ) ----------------------< cut here