diff --git a/build/timestamps.txt b/build/timestamps.txt index 55b4aa7db..38d974a68 100644 --- a/build/timestamps.txt +++ b/build/timestamps.txt @@ -1041,6 +1041,7 @@ ksc/nscan.8 197709130702.35 ksc/pagser.49 198510290114.12 ksc/qmail.614 198808140012.29 ksc/timer.115 198712180208.41 +ksc/timrts.42 198504142018.45 ksc/zotz.12 198712150308.01 kshack/1proc.bugs 198605312354.25 kshack/ainote.8 198610240402.35 diff --git a/src/ksc/timrts.42 b/src/ksc/timrts.42 new file mode 100755 index 000000000..e5db67454 --- /dev/null +++ b/src/ksc/timrts.42 @@ -0,0 +1,482 @@ +SUBTTL Time routines - readin', ritin', & rithmetic for dates/times + +IFN $$OUT*$$OTIM, .FATAL OUT pkg now uses DATIME library + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; These routines will work fine unless dumped after +;;; execution. To ensure complete winnage, call PUSHJ P,TIMINI +;;; to initialize words such as TMDSTF and TMSYST. +;;; +;;; Internal format time word: a single word serves to define date/time +;;; as follows. This is identical to ITS DSK format date, except +;;; for the use of bit 1.1 as Daylight Saving Time indicator. (ugh!) + +; Mask Field Bits Range Var. Variable range + +TM%DST== 1 ; 1.1 0-1 half-sec or DST indicator. +TM%SEC== 777776 ; 2.9-1.2 0-131K seconds 0-86399. +TM%DAY== 37,,0 ; 3.5-3.1 0-31 days 1-31 +TM%MON== 740,,0 ; 3.9-3.6 0-15 months 1-12 +TM%YR== 177000,,0 ; 4.7-4.1 0-127 years 0-127 relative to 1900 (1900-2027) + +TM$SEC==(.BP TM%SEC,) ; Define BP LH's into each field. +TM$DAY==(.BP TM%DAY,) +TM$MON==(.BP TM%MON,) +TM$YR== (.BP TM%YR,) + +GMTDIF==5 ; # hours difference of local zone from GMT. + + ; Table for printing day-of-week, indexed by 1-7. + ; Use TIMADY to find abs time in days; divide by 7 and + ; remainder (plus 1) is index into DOW tables. +DOWTB: ; preferred label. +TDAYTB: 0 + IRP D,,[MON,TUE,WED,THU,FRI,SAT,SUN] + 3,,[ASCIZ /D/] ; All strings of length 3. + TERMIN + + ; Table for long-form Day-Of-Week, indexed by 1-7. +LDOWTB: 0 + IRP D,,[Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday] + .LENGTH "D",,[ASCIZ "D"] + TERMIN + + ; Table for printing month, indexed by 1-12. +MONTAB: 0 + IRP M,,[JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC] + 3,,[ASCIZ /M/] ; All strings length 3. + TERMIN + + ; Table for printing month, indexed by 1-12. +LMNTAB: 0 + IRP M,,[January,February,March,April,May,June,July,August,September,October,November,December] + .LENGTH "M",,[ASCIZ "M"] + TERMIN + + ; Table containing # of days in each month, assuming non-leap year. +TMONLN: 0 ; no 0'th month. + ;JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC + 31. ? 28. ? 31. ? 30. ? 31. ? 30. ? 31. ? 31. ? 30. ? 31. ? 30. ? 31. + + ; Special table to allow figuring how many days so far + ; in this year. Indexed by month # (1-12) gives # days + ; taken up by months preceding it. Assumes non-leap year. +TMONTB: 0 + 0 + 31. ;+jan + 59. ;+jan+feb + 90. ;+jan+feb+mar... + 120. ;...+apr + 151. ;...+may + 181. ;...+jun + 212. ;...+jul + 243. ;...+aug + 273. ;...+sep + 304. ;...+oct + 334. ;...+nov + + + +LVAR TMBUF: BLOCK 8. ; Various composed strings stored here. + + +; TIMINI - Initializes time routines and makes sure system knows the +; time; fails to skip if it doesn't. + +TIMINI: PUSH P,A + SETZM TMDSTF ; Clear DST flag + SETZM TMSYST ; and time system started. + SYSCAL RQDATE,[CRET A] ; Try to get time. + JSR SYSLOS + CAME A,[-1] ; Skip if don't know time. + AOS -1(P) ; Else skip on return! + POP P,A + POPJ P, + + +; TIMGET - Returns internal time word in A. +; TIMGT - Similar but doesn't bother to hack DST bit. + +TIMGT: SYSCAL RQDATE,[CRET A] ; Get DSK format date. + JSR SYSLOS + CAMN A,[-1] + JSR AUTPSY ; Ugh, system doesn't know time. + POPJ P, +TIMGET: SYSCAL RQDATE,[CRET A] + JSR SYSLOS + CAMN A,[-1] ; Make sure system knows time. + JSR AUTPSY + TRZ A,TM%DST ; Assume Standard Time in effect. + SKIPN TMDSTF ; Skip if Standard/Savings flag known. + PUSHJ P,TMDSTG ; If not, get it. + SKIPGE TMDSTF ; Now if Daylight Savings in effect, + TRO A,TM%DST ; set flag. + POPJ P, + +LVAR TMDSTF: 0 ; Flag for Daylight Savings Time. + Standard, - Savings, 0 don't know. +TMDSTG: PUSH P,A ; Routine to set TMDSTF. + .RYEAR A, + CAMN A,[-1] + JSR AUTPSY + SETOM TMDSTF ; Assume DST in effect. + TLNN A,100000 ; If bit is set, that's right. + MOVMS TMDSTF ; Else Standard, make flag positive. + POP P,A + POPJ P, + +LVAR TLZONP: 0 ; Local Timezone, standard (BP to ASCIZ) +LVAR TLZONQ: 0 ; Local Timezone, Daylite Savings (BP to ASCIZ) + +; TMZONG - Get Local Time-Zone strings. +; At moment simply sets, since ITS has no way of asking for +; time-zone... TNX version could win though. +TMZONG: PUSH P,A + MOVE A,[440700,,[ASCIZ /EST/]] + MOVEM A,TLZONP + MOVE A,[440700,,[ASCIZ /EDT/]] + MOVEM A,TLZONQ + POP P,A + RET + + +; TIMGTN - Gets 32-bit "Network time" in A. This is GMT in # seconds since +; 1/1/00. + +TIMGTN: PUSHAE P,[B,C] + .RLPDTM A, ; Get in A, # secs since beg of year. + CAME A,[-1] ; in B, the year + CAMN B,[-1] + JSR AUTPSY ; If either is -1, time not known. + CAIGE B, ; If 4.9 on, it's past Feb 28 and non-leap-yr + SUBI A,24.*3600. ; so subtract one day from .RLPDTM misfeature. + TLNE B,100000 ; Bit 4.7 = Daylight Savings time? + SUBI A,3600. ; If on, subtract one hour to get Standard. + MOVEI B,-1900.(B) ; Get year, relative to 1900. + MOVEI C,-1(B) ; Adjust and + LSH C,-2 ; Get # leap years since 1900 not including this year. + IMULI B,365. ; Find # days in years thus far + ADDI B,(C) ; Plus # LY's, to get total days in years past. + IMULI B,86400. ; Now get # seconds in all them days. + ADD A,B ; and produce total seconds since 1/1/00 ! + ADD A,[GMTDIF*3600.] ; Adjust to GMT. + POPAE P,[C,B] + POPJ P, + +IFNDEF $$OUT,$$OUT==0 ? $$OTIM==0 +IFE $$OUT*$$OTIM,[ + ; Don't need following cruft any more if using OUT. + +; TIMDAT - Takes time word in A, returns ASCNT ptr in A to string +; at TMBUF of format . + +TIMDAT: PUSHAE P,[B,C,D] + MOVE D,[440700,,TMBUF] ; Set up BP for date composer. + PUSHJ P,TMDAT + MOVE A,[8.,,TMBUF] + POPAE P,[D,C,B] + POPJ P, + +; TIMTIM - Like TIMDAT, but string is time in format . + +TIMTIM: PUSHAE P,[B,C,D] + MOVE D,[440700,,TMBUF] + PUSHJ P,TMTIM + MOVE A,[8.,,TMBUF] + POPAE P,[D,C,B] + POPJ P, + +; TIMDTM - Combination of TIMDAT and TIMTIM, produces . + +TIMDTM: PUSHAE P,[B,C,D] + MOVE D,[440700,,TMBUF] + PUSHJ P,TMDAT + MOVEI B,40 ; Put in a spacer. + IDPB B,D + PUSHJ P,TMTIM + MOVE A,[17.,,TMBUF] + POPAE P,[D,C,B] + POPJ P, + +; TMDAT - Internal rtn to deposit MM/DD/YY using BP in D. +; Takes time wd in A, clobbers B and C. + +TMDAT: PUSH P,E + SKIPA E,[-3,,[ TM$MON,,A + TM$DAY,,A + TM$YR,,A ] ] +TMDT2: IDPB B,D + LDB B,(E) ; Get numerical value into B. + IDIVI B,10. ; Divide into 2 digits. + MOVEI B,"0(B) + IDPB B,D ; Output first, + MOVEI B,"0(C) + IDPB B,D ; and second. + MOVEI B,"/ ; Set up separator, in case looping again. + AOBJN E,TMDT2 + POP P,E + POPJ P, + +; TMTIM - Internal rtn to deposit HH:MM:SS using BP in D. +; Takes time wd in A, clobbers B and C. + +TMTIM: PUSH P,E + HRRZ B,A ; For storage of hr, min, sec. + LSH B,-1 + IDIVI B,60. ; Get secs + PUSH P,C ; save + IDIVI B,60. ; Get hr and mins + PUSH P,C ; Save mins too. + MOVSI E,-3 + JRST TMTM3 +TMTM2: IDPB B,D + POP P,B ; Get numerical value into B. +TMTM3: IDIVI B,10. ; Divide into 2 digits. + MOVEI B,"0(B) + IDPB B,D ; Output first, + MOVEI B,"0(C) + IDPB B,D ; and second. + MOVEI B,": ; Set up separator, in case looping again. + AOBJN E,TMTM2 + POP P,E + POPJ P, + + +; TIMEXP - Takes time wd in A, returns ASCNT ptr to string in TMBUF +; of the form <7 AUG 1976 0831-EDT>. +; TIMENG - similar but uses current time and takes no arg. + +TIMENG: PUSHJ P,TIMGET +TIMEXP: PUSHAE P,[B,C] + PUSH P,[19.,,TMBUF] ; Save probable result on stack. + PUSH P,A ; Save time wd. + MOVE C,[440700,,TMBUF] ; Put string in special location. + LDB A,[TM$DAY,,(P)] ;get day + IDIVI A,10. + JUMPN A,[MOVEI A,"0(A) + IDPB A,C + MOVSI A,1 + ADDM A,-1(P) ; increment length of ASCNT ptr to return. + JRST .+1] + MOVEI A,"0(B) + IDPB A,C + MOVEI A,40 + IDPB A,C ;space out + LDB A,[TM$MON,,(P)] ;get month + MOVE A,MONTAB(A) ;get ptr to string for it + HRLI A,440700 + ILDB B,A + IDPB B,C + ILDB B,A + IDPB B,C + ILDB B,A + IDPB B,C ;3 chars + MOVEI A,40 + IDPB A,C ;space out + LDB A,[TM$YR,,(P)] ;get year + ADDI A,1900. ;get real year + PUSHJ P,TIMCVT + MOVEI A,40 ;space out + IDPB A,C + HRRZ A,(P) ;get half-sec since midnight + IDIVI A,60.*2 ; get mins + IDIVI A,60. ; Get hrs in A, mins in B + IMULI A,100. ; space hrs out 2 digits + ADD A,B ;get total 'time' + + MOVEI B,"0 ;crock to add (!) zeros so stupid + CAIGE A,1000. ;parsers will be happy (4 digits total) + IDPB B,C + CAIGE A,100. + IDPB B,C + CAIGE A,10. + IDPB B,C + PUSHJ P,TIMCVT + + POP P,A ; Restore to test DST bit. + MOVE B,[440700,,[ASCIZ /-EST/]] + TRNE A,TM%DST + MOVE B,[440700,,[ASCIZ /-EDT/]] ; Use EDT if DST in effect. + ILDB A,B + IDPB A,C ;note nice hack..makes asciz when done. + JUMPN A,.-2 + POP P,A ; Return ASCNT ptr to result + POPAE P,[C,B] + POPJ P, + +TIMCVT: IDIVI A,10. + JUMPE A,TIMCV1 + PUSH P,B + PUSHJ P,TIMCVT + POP P,B +TIMCV1: ADDI B,"0 + IDPB B,C + POPJ P, + +; LTMEXP - Takes time wd in A, returns ASCNT ptr to string in TMBUF +; of the form <7 August 1976 08:31 EDT>. +; LTMENG - similar but uses current time and takes no arg. + +LTMENG: PUSHJ P,TIMGET +LTMEXP: PUSHAE P,[B,C,D] + PUSH P,A ; Save time wd. + MOVE C,[440700,,TMBUF] ; Put string in special location. + MOVEI D,17. + LDB A,[TM$DAY,,(P)] ;get day + IDIVI A,10. + JUMPN A,[MOVEI A,"0(A) + IDPB A,C + AOJA D,.+1 ] + MOVEI A,"0(B) + IDPB A,C + MOVEI A,40 + IDPB A,C ;space out + LDB A,[TM$MON,,(P)] ;get month + MOVE A,LMNTAB(A) ;get ptr to string for it + HRLI A,440700 + ILDB B,A +LTME1: IDPB B,C + ADDI D,1 + ILDB B,A + JUMPN B,LTME1 + MOVEI A,40 + IDPB A,C ;space out + LDB A,[TM$YR,,(P)] ;get year + ADDI A,1900. ;get real year + PUSHJ P,TIMCVT + MOVEI A,40 ;space out + IDPB A,C + HRRZ A,(P) ;get half-sec since midnight + IDIVI A,60.*2 ; get mins + IDIVI A,60. ; Get hrs in A, mins in B + PUSH P,B + IDIVI A,10. + ADDI A,"0 + IDPB A,C + ADDI B,"0 + IDPB B,C + MOVEI A,": + IDPB A,C + POP P,A + IDIVI A,10. + ADDI A,"0 + IDPB A,C + ADDI B,"0 + IDPB B,C + + POP P,A ; Restore to test DST bit. + MOVE B,[440700,,[ASCIZ / EST/]] + TRNE A,TM%DST + MOVE B,[440700,,[ASCIZ / EDT/]] ; Use EDT if DST in effect. + ILDB A,B + IDPB A,C ;note nice hack..makes asciz when done. + JUMPN A,.-2 + MOVS A,D ; Return ASCNT ptr to result + HRRI A,TMBUF + POPAE P,[D,C,B] + POPJ P, +] ;IFE $$OUT*$$OTIM + +; TIMADY - Time in Absolute Days. Converts time wd in A to absolute +; # of days since Jan 1 1900, returns value in same. + +TIMADY: PUSHAE P,[B,C] + LDB B,[TM$MON,,A] ;get month # + LDB C,[TM$DAY,,A] ;get day # + ADD C,TMONTB(B) ;add days in months thus far to # days thus far in month + LDB A,[TM$YR,,A] ;get year + JUMPE A,TIMAD7 ; Avoid 1900 lossage. + TRNE A,3 ;is this a leap yr? (only works until 2000) + JRST .+3 ;no, skip additional day + CAIL B,3 ;leap yr... is it after feb? + ADDI C,1 ;yes, add extra day. + MOVEI B,-1(A) ;adjust, and + LSH B,-2 ;get # of l.y. since 1900, not incl. this yr + IMULI A,365. ;# yrs times 365 + ADDI A,(B) ;plus # prior l.y.'s (# extra days) +TIMAD7: ADDI A,-1(C) ;plus days so far this yr (-1 because day 1 of month + POPAE P,[C,B] ; is really 0) + POPJ P, + +; TIMASC - Similar to TIMADY, but returns value in seconds. +; Value is 31,536,000. per yr (32 bits for 136 yrs). + +TIMASC: PUSH P,B + HRRZ B,A ; Get # half-secs + LSH B,-1 ; # secs. + PUSHJ P,TIMADY ; Get # days. + IMULI A,24.*60.*60. + ADDI A,(B) ; Add # secs for today to # secs of days past. + POP P,B + POPJ P, + +; TIMCAD - Convert Absolute Days to time word. Inverse of TIMADY. +; Takes # days since 1/1/00 in A, returns time wd in same. + +TIMCAD: PUSHAE P,[B,C] + IDIVI A,365. ;find # "normal" years. + JUMPE A,TIMCA2 ; Avoid 1900 lossage. + MOVEI C,-1(A) ;now see how many leap years covered (not incl current) + LSH C,-2 ;divide by 4 to get # leap yrs + SUBI B,(C) ;adjust cnt of remaining days + JUMPL B,[SUBI A,1 ;backed past year boundary? bump down # yrs + ADDI B,365. ;if negative, must adjust again + TRNN A,3 ;if in leap year, + ADDI B,1 ;add one more since 366. days in LY + JRST .+1] + +TIMCA2: MOVEI C,12. + CAMGE B,TMONTB(C) ;compare # days in year with # days after each month + SOJG C,.-1 ;loop (#1 index has 0 value, so it will stop) + TRNN A,3 ;leap year? + JRST [ CAIGE C,3 ;ugh, yes. but if in jan or feb, + JRST .+1 ;saved. else it's after feb and must hack it. + SUBI B,1 ;lower value + CAMGE B,TMONTB(C) ;still wins? + SUBI C,1 ;if not, bump month down. + CAIN C,2 ;if now in Feb, + AOJA B,.+1 ;restore value so subtracting TMONTB gives 29, not 28. + JRST .+1] + SUB B,TMONTB(C) ;get # of day within month + DPB A,[TM$YR,,A] ;deposit year + DPB C,[TM$MON,,A] ;and month + MOVEI B,1(B) ; First day of month is day 1, not day 0. + DPB B,[TM$DAY,,A] ;and day. + ANDCMI A,-1 ;Zap RH to start of day. + POPAE P,[C,B] + POPJ P, + +; TIMCAS - Converts Absolute Seconds to time word. +; Argument in A (# secs since 1/1/00), returns time wd in A. + +TIMCAS: PUSH P,B + IDIVI A,24.*60.*60. ; Get remainder of # secs in day + PUSHJ P,TIMCAD ; Find time wd given # days. + LSH B,1 + ADDI A,(B) ; Add in # half secs. + POP P,B + POPJ P, + +; TIMASY - Converts internal time wd. to system time +; ( 30'ths of second since system startup). Will return +; negative value if time specified is BEFORE system startup. + +TIMASY: PUSHJ P,TIMASC ; Convert given time to absolute # secs. + SKIPN TMSYST ; If don't already have system startup time, + PUSHJ P,TMSYSG ; must get it. + SUB A,TMSYST ; Find difference in secs. + IMULI A,30. ; Turn into 30'ths. + POPJ P, + +LVAR TMSYST: 0 ; Holds time of system startup in absolute # secs. +TMSYSG: PUSHAE P,[A,B,C] + PUSHJ P,TIMGT ; Get current date/time in internal format + .RDTIME B, ; And time since system startup. + PUSHJ P,TIMASC ; Convert date/time to abs # seconds. + IDIVI B,30. ; Similarly get # secs since system startup. + SUB A,B ; Now get abs # secs at which system started. + MOVEM A,TMSYST ; Store it. + POPAE P,[C,B,A] + POPJ P, + + \ No newline at end of file