mirror of
https://github.com/PDP-10/its.git
synced 2026-01-17 00:33:22 +00:00
1139 lines
31 KiB
Plaintext
Executable File
1139 lines
31 KiB
Plaintext
Executable File
.BEGIN DATIME ;-*-MIDAS-*-
|
||
|
||
SUBTTL Time routines - readin', ritin', & rithmetic for dates/times
|
||
|
||
;We assume that there are consecutive accumulators A, B, C, D and E,
|
||
;and that the stack is in P. No routine clobbers ACs other than the
|
||
;ones it is documented to clobber, and none touches even temporarily
|
||
;any AC other than A, B, C, D, E and P.
|
||
;All impure storage is allocated using .SCALAR
|
||
|
||
;Symbols defined by the user to select parts of this file:
|
||
IFNDEF $$OUT,$$OUT==0 ;include routines for outputting times.
|
||
IFNDEF $$DSTB,$$DSTB==0 ;hack DST bit in time word.
|
||
; This only effects TIMGET currently.
|
||
IFNDEF $$ABS,$$ABS==0 ;include conversions to/from absolute days/seconds
|
||
IFNDEF $$OUTF,$$OUTF==0 ;include rtns for english-style ("fancy") output.
|
||
IFNDEF $$RFC,$$RFC==0 ;include rtns for RFC### style output.
|
||
IFNDEF $$OUTT,$$OUTT==0 ;include basic tables for fancy output.
|
||
IFNDEF $$OUTZ,$$OUTZ==0 ;include output rtns that know about time zones.
|
||
IFNDEF $$IN,$$IN==0 ;include rtns for reading times
|
||
IFNDEF $$INF,$$INF==0 ;include rtns for parsing "3 AUG 1971 0800"
|
||
IFNDEF $$SVNG,$$SVNG==0 ;include handling of daylight savings time.
|
||
IFNDEF $$UPTM,$$UPTM==0 ;include rtns for system uptime in 30'ths conversion.
|
||
IFNDEF $$CURD,$$CURD==1 ;if year missing, use current year
|
||
|
||
;Interdependencies of the various selectable submodules:
|
||
|
||
IFN $$OUTZ,$$OUTF==1 ? $$SVNG==1
|
||
IFN $$UPTM,$$ABS==1
|
||
IFN $$SVNG,$$ABS==1
|
||
IFN $$RFC,$$SVNG==1
|
||
|
||
.AUXIL ;Don't mention all our internal symbols in crefs.
|
||
|
||
;PRINT VERSION NUMBER
|
||
.TYO6 .IFNM1
|
||
.TYO 40
|
||
.TYO6 .IFNM2
|
||
PRINTX/ included in this assembly.
|
||
/
|
||
|
||
DEFINE SYSCAL NAME,ARGS
|
||
.CALL [SETZ ? SIXBIT/NAME/ ? ARGS ((SETZ))]
|
||
TERMIN
|
||
|
||
;;; A time word is a single word describing the date and time in ITS DSK
|
||
;;; format, except that we use bit 1.1 as Daylight Saving Time indicator.
|
||
|
||
; 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$DST==(.BP TM%DST,) ; Define BP LH's into each field.
|
||
TM$SEC==(.BP TM%SEC,)
|
||
TM$DAY==(.BP TM%DAY,)
|
||
TM$MON==(.BP TM%MON,)
|
||
TM$YR== (.BP TM%YR,)
|
||
|
||
ESTDIF==5 ; # hours difference of EST from GMT.
|
||
DWFUDG==1 ; day of week of 1st day of 1900.
|
||
|
||
|
||
IFE $$DSTB, TIMGET:
|
||
TIMGT: SYSCAL RQDATE,[%CLOUT,, A] ; Get DSK format date.
|
||
SETO A, ; Ugh, system doesn't know time.
|
||
POPJ P,
|
||
|
||
IFN $$DSTB,[
|
||
TIMGET: PUSH P,B
|
||
SYSCAL RQDATE,[%CLOUT,,A] ; Get DSK format date.
|
||
SETO A, ; Eh?
|
||
.RYEAR B, ; 4.6 => time known, 4.7 => DST in effect
|
||
TLNE B,40000
|
||
CAMN A,[-1] ; Make sure system knows time.
|
||
JRST TIMGE9
|
||
TRZ A,TM%DST ; Assume Standard Time in effect.
|
||
TLNE B,100000 ; Now if Daylight Savings in effect,
|
||
TRO A,TM%DST ; set flag.
|
||
TIMGE9: POP P,B
|
||
POPJ P,
|
||
] ;$$DSTB
|
||
|
||
IFN $$OUT,[ ;Routines for simple output of times.
|
||
|
||
; DATASC - Deposit MM/DD/YY using BP in D.
|
||
; Deposits a trailing null, which D is left ready to IDPB.
|
||
; Takes time wd in A, clobbers B and C.
|
||
|
||
DATASC: PUSH P,B
|
||
PUSH P,C
|
||
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,100.
|
||
MOVE B,C
|
||
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
|
||
TIMTMX: MOVE B,D ; Follow the string with a null so it's asciz.
|
||
SETZ C,
|
||
IDPB C,B
|
||
POP P,E
|
||
POP P,C
|
||
POP P,B
|
||
POPJ P,
|
||
|
||
; TIMASC - Deposit HH:MM:SS using BP in D given a time word in A.
|
||
; Deposits a trailing null, which D is left ready to IDPB.
|
||
; Takes time wd in A.
|
||
|
||
TIMASC: PUSH P,B
|
||
PUSH P,C
|
||
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
|
||
JRST TIMTMX
|
||
|
||
; TWDASC - Given time word in A, send YY/MM/DD HH:MM:SS down b.p. in D.
|
||
|
||
TWDASC: PUSHJ P,DATASC
|
||
PUSH P,A
|
||
MOVEI A,40
|
||
IDPB A,D
|
||
POP P,A
|
||
JRST TIMASC
|
||
|
||
] ;end ifn $$out
|
||
|
||
IFN $$OUTZ,[ ;Routines for fancy output of dates, including time zones.
|
||
|
||
; TIMSTD - Takes a time word which is assumed to be in standard time, and
|
||
; converts it to daylight time if necessary, then prints like TIMEXP.
|
||
|
||
TIMSTD: PUSH P,A
|
||
PUSH P,B
|
||
PUSH P,[0] ;push 0, assuming it's standard time.
|
||
MOVEI B,3600.
|
||
PUSHJ P,ODAYL
|
||
SOSA (P) ;if daylight time, replace 0 with -1 and convert the time.
|
||
CAIA
|
||
PUSHJ P,TIMADD
|
||
JRST TIMEX1
|
||
|
||
; TIMEXP - Takes time wd in A, deposits through D a string of the form
|
||
; of the form <7 AUG 1976 0831-EDT>.
|
||
; Assumes that the time is in either daylight or savings time,
|
||
; whichever is appropriate for the specified time of year.
|
||
|
||
TIMEXP: PUSH P,A
|
||
PUSH P,B
|
||
PUSH P,[0]
|
||
PUSHJ P,IDAYL
|
||
SETOM (P)
|
||
TIMEX1: PUSHJ P,TIMENG
|
||
MOVE B,[440700,,[ASCIZ /-EST/]]
|
||
SKIPE (P)
|
||
MOVE B,[440700,,[ASCIZ /-EDT/]] ; Use EDT if DST in effect.
|
||
TIMEX2: ILDB A,B
|
||
IDPB A,D
|
||
CAIE A,"T
|
||
JRST TIMEX2
|
||
SETZ A,
|
||
MOVE B,D ;Stick a 0 at the end to make asciz, but don't advance D.
|
||
IDPB A,B
|
||
SUB P,[1,,1]
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
] ;end ifn $$outz,
|
||
|
||
IFN $$OUTF,[ ;Routines for fancy output of dates.
|
||
|
||
; TIMENG - Takes time wd in A, deposits through D a string of the form
|
||
; of the form "7 AUG 1976 0831", followed by a null, which we don't
|
||
; advance D past.
|
||
|
||
TIMENG: PUSHJ P,DATENG ;Output "7 AUG 1976".
|
||
PUSH P,A
|
||
PUSH P,B
|
||
MOVEI A,40 ;space out
|
||
IDPB A,D
|
||
IDPB A,D
|
||
HRRZ A,-1(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,D
|
||
CAIGE A,100.
|
||
IDPB B,D
|
||
CAIGE A,10.
|
||
IDPB B,D
|
||
PUSHJ P,TIMCVT
|
||
PUSH P,D
|
||
SETZ B,
|
||
IDPB B,D
|
||
POP P,D
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
TIMCVT: IDIVI A,10.
|
||
JUMPE A,TIMCV1
|
||
PUSH P,B
|
||
PUSHJ P,TIMCVT
|
||
POP P,B
|
||
TIMCV1: ADDI B,"0
|
||
IDPB B,D
|
||
POPJ P,
|
||
|
||
|
||
;Output just the date from the time word in A, as "7 AUG 1976",
|
||
;down bp in D, sticking a null after the string.
|
||
DATENG: PUSH P,A
|
||
PUSH P,B
|
||
LDB A,[TM$DAY,,-1(P)] ;get day
|
||
IDIVI A,10.
|
||
JUMPN A,[MOVEI A,"0(A)
|
||
IDPB A,D
|
||
JRST .+1]
|
||
MOVEI A,"0(B)
|
||
IDPB A,D
|
||
MOVEI A,40
|
||
IDPB A,D ;space out
|
||
LDB A,[TM$MON,,-1(P)] ;get month
|
||
MOVE A,MONTAB(A) ;get ptr to string for it
|
||
HRLI A,440700
|
||
ILDB B,A
|
||
IDPB B,D
|
||
ILDB B,A
|
||
IDPB B,D
|
||
ILDB B,A
|
||
IDPB B,D ;3 chars
|
||
MOVEI A,40
|
||
IDPB A,D ;space out
|
||
LDB A,[TM$YR,,-1(P)] ;get year
|
||
ADDI A,1900. ;get real year
|
||
PUSHJ P,TIMCVT
|
||
MOVE B,D ;Pad with a null at the end, but don't move over it.
|
||
SETZ A,
|
||
IDPB A,B
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
|
||
IFN $$DSTB,[
|
||
|
||
; LTMEXP - Takes time wd in A, deposits through D a string of the form
|
||
; of the form "7 August 1976 08:31 EDT".
|
||
; Returns in A an ASCNT ptr to the string.
|
||
; LTMENG - similar but uses current time and takes no arg.
|
||
|
||
.SCALAR TIMBP
|
||
|
||
LTMENG: PUSHJ P,TIMGET
|
||
LTMEXP: MOVEM D,TIMBP
|
||
PUSH P,B
|
||
PUSH P,C
|
||
PUSH P,D
|
||
PUSH P,A ; Save time wd.
|
||
MOVE C,TIMBP ; Get Bp to result.
|
||
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
|
||
MOVE A,TIMBP
|
||
POP P,D
|
||
POP P,C
|
||
POP P,B
|
||
POPJ P,
|
||
|
||
];IFN $$DSTB
|
||
];END IFN $$OUTF
|
||
|
||
ifn $$rfc,[
|
||
|
||
; TIMRFC - Takes time wd in A, deposits through D a string of the form
|
||
; of the form "7 MAR 85 09:31:12 EDT".
|
||
; (Does not tie off the string.)
|
||
|
||
TIMRFC: PUSH P,A
|
||
PUSH P,B
|
||
LDB A,[TM$DAY,,-1(P)] ;get day
|
||
IDIVI A,10.
|
||
JUMPN A,[MOVEI A,"0(A)
|
||
IDPB A,D
|
||
JRST .+1]
|
||
MOVEI A,"0(B)
|
||
IDPB A,D
|
||
MOVEI A,40
|
||
IDPB A,D ;space out
|
||
LDB A,[TM$MON,,-1(P)] ;get month
|
||
MOVE A,LMNTAB(A) ;get ptr to string for it
|
||
HRLI A,440700
|
||
ILDB B,A
|
||
IDPB B,D
|
||
ILDB B,A
|
||
IDPB B,D
|
||
ILDB B,A
|
||
IDPB B,D ;3 chars
|
||
MOVEI A,40
|
||
IDPB A,D ;space out
|
||
LDB A,[TM$YR,,-1(P)] ;get year
|
||
PUSHJ P,TIMCVT ;Output "85"
|
||
MOVEI A,40 ;space out
|
||
IDPB A,D
|
||
IDPB A,D
|
||
MOVE A,-1(P) ;Recover time word.
|
||
PUSHJ P,TIMASC ;Output "09:31:12".
|
||
MOVE B,[440700,,[ASCIZ / EST/]]
|
||
PUSHJ P,IDAYL
|
||
MOVE B,[440700,,[ASCIZ / EDT/]]
|
||
TIMRZN: ILDB A,B
|
||
IDPB A,D ;Output " EST"
|
||
CAIE A,"T
|
||
JRST TIMRZN
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
] ;end ifn $$rfc
|
||
|
||
;;; Routines for fancy output of time.
|
||
|
||
IFN $$OUTT,[
|
||
;To print the Day-of-week, call TIMDOW to convert a time word to
|
||
;day-of-week # (0-6) in B, then use 440700,,DOWTAB(B) or the contents
|
||
;of DOWLNG(B) as a b.p. to type.
|
||
|
||
;Table of days of the week.
|
||
DOWTAB: IRP D,,[Sun,Mon,Tue,Wed,Thu,Fri,Sat]
|
||
ASCIZ /D/ ; All strings of length 3.
|
||
TERMIN
|
||
|
||
DOWLNG: IRPS D,,Sunday Monday Tuesday Wednesday Thursday Friday Saturday
|
||
[ASCIZ /D/]
|
||
TERMIN
|
||
|
||
];END IFN $$OUTT
|
||
|
||
;;; Tables which fancy routines need.
|
||
|
||
IFN $$OUTT\$$OUTF\$$INF,[
|
||
; Table for printing month, indexed by 1-12.
|
||
MONTAB: 0
|
||
IRP M,,[JANUARY,FEBRUARY,MARCH,APRIL,MAY,JUNE,JULY,AUGUST,SEPTEMBER,OCTOBER,NOVEMBER,DECEMBER]
|
||
[ASCIZ /M/]
|
||
TERMIN
|
||
|
||
; Prettier ASCNT versions of above, used only by certain routines.
|
||
; Maybe someday make most rtns in this library use these tables.
|
||
|
||
LMNTAB: 0
|
||
IRP M,,[January,February,March,April,May,June,July,August,September,October,November,December]
|
||
.LENGTH "M",,[ASCIZ "M"]
|
||
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
|
||
|
||
];END IFN $$OUTF\$$OUTT\$$INF
|
||
|
||
|
||
IFN $$IN,[ ;Routines for reading in the date and time in a simple format.
|
||
|
||
;Takes a b.p. in D to a time in the format mm/dd/yy hh:mm:ss
|
||
;and returns the corresponding time word in A.
|
||
;Leaves D pointing at the terminator (having LDB'd it).
|
||
ASCTWD: PUSH P,B
|
||
PUSH P,C
|
||
SETZ A, ;Initialize all fields of date to 0.
|
||
MOVEI B,40
|
||
PUSHJ P,NUMIN ;Read month number.
|
||
CAIN B,": ;If :, default to somtime today
|
||
JRST ASCTI5
|
||
CAIE B,"/ ;If month is 0 and not followed by : or /,
|
||
; assume date null,
|
||
JUMPE C,[ ;so use current date and time.
|
||
PUSHJ P,TIMGT
|
||
JRST ASCTIX]
|
||
DPB C,[270400,,A]
|
||
PUSHJ P,NUMINS ;Day of month.
|
||
DPB C,[220500,,A]
|
||
CAIN B,40
|
||
JRST [ ILDB B,D
|
||
JRST .-1]
|
||
CAIN B,"/ ;Year not specified =>
|
||
JRST ASCTI1
|
||
SYSCAL RQDATE,[%CLOUT,,C]
|
||
SETZI C,
|
||
LDB C,[330700,,C] ; use today's year.
|
||
JRST ASCTI2
|
||
|
||
ASCTI5: SYSCAL RQDATE,[%CLOUT,,A]
|
||
SETZI A,
|
||
HLLZ A,A
|
||
JRST ASCTI6
|
||
|
||
ASCTI1: PUSHJ P,NUMINS ;Year number.
|
||
ASCTI2: DPB C,[330700,,A]
|
||
PUSHJ P,NUMIN ;Hour.
|
||
ASCTI6: IMULI C,3600.*2
|
||
ADD A,C
|
||
PUSHJ P,NUMINC ;Minute.
|
||
IMULI C,60.*2
|
||
ADD A,C
|
||
PUSHJ P,NUMINC ;Second
|
||
ADD A,C
|
||
ADD A,C
|
||
ASCTIX: POP P,C
|
||
POP P,B
|
||
POPJ P,
|
||
|
||
;Read a number, but insist on skipping over a slash first.
|
||
NUMINS: CAIN B,40
|
||
JRST [ ILDB B,D ;Ignore leading spaces.
|
||
JRST NUMINS]
|
||
SETZ C,
|
||
CAIE B,"/ ;Return 0 if no slash to skip over.
|
||
POPJ P,
|
||
JRST NUMIN0
|
||
] ;end ifn $$in
|
||
|
||
IFN $$INF,[ ;Routines for reading in English-style dates and times.
|
||
|
||
;Read the date and then the time off the b.p. in D, returning time word in A.
|
||
;Skips if the supplied text is valid. Leaves terminating char in B. Clobbers C.
|
||
|
||
ENGTWD: PUSHJ P,ENGDAT ;Read date as time word in A.
|
||
POPJ P,
|
||
PUSHJ P,[PUSH P,A ;Read hours and minutes,
|
||
JRST ENGT0] ;sticking it into time word holding date.
|
||
POPJ P,
|
||
JRST ENGSEC ;Read seconds, adding them into time-word in A.
|
||
|
||
.SCALAR ENGDTP ;Holds pdl-level for error return in ENGDAT
|
||
|
||
;Read the date off the b.p. in D, returning it as a time-word in A.
|
||
;Skips if it's valid. Leaves terminating char in B. Clobbers C.
|
||
|
||
ENGDAT: PUSH P,ENGDTP
|
||
MOVEM P,ENGDTP
|
||
PUSH P,[0] ;Accumulate the time-word in this word, (P).
|
||
MOVEI B,40
|
||
PUSHJ P,MONTH ;Try to read a month name.
|
||
JRST ENGD1 ;Can't => may be numeric, or name may be after day number.
|
||
DPB A,[TM$MON,,(P)] ;Store number corresponding to month name.
|
||
PUSHJ P,NONSEP ;A day number must follow, after a slash or dash, perhaps.
|
||
PUSHJ P,NUMIN
|
||
CAIL C,32.
|
||
JRST ENGDLZ
|
||
DPB C,[TM$DAY,,(P)] ;Save the day number.
|
||
ENGDYR: PUSHJ P,NONSPC ;There may be a comma here, before the year.
|
||
CAIE B,",
|
||
CAIN B,"/
|
||
CAIA
|
||
CAIN B,"-
|
||
ILDB B,D
|
||
PUSHJ P,NUMIN ;Read the year number.
|
||
MOVE A,C
|
||
IFN $$CURD,[
|
||
JUMPE A,[ ;none => use current year.
|
||
SYSCAL RQDATE,[%CLOUT,,A]
|
||
SETZ A,
|
||
LDB B,[330700,,A]
|
||
JRST .+2]
|
||
];$$CURD
|
||
.ELSE, JUMPE A,ENGDOK
|
||
IDIVI A,100. ;Extract low two digits of year and put in time-word.
|
||
DPB B,[TM$YR,,(P)]
|
||
ENGDOK: POP P,A
|
||
AOS -1(P)
|
||
ENGDLZ: MOVE P,ENGDTP ;Come here to fail-return from ENGDAT
|
||
POP P,ENGDTP
|
||
POPJ P,
|
||
|
||
;Here in ENGDAT if date doesn't start with a month name.
|
||
ENGD1: PUSHJ P,NUMIN ;Number might be day or month.
|
||
PUSHJ P,NONSEP
|
||
PUSH P,C ;Save that number.
|
||
PUSHJ P,MONTH ;Month name after the number?
|
||
JRST [ PUSHJ P,NUMIN ; No, two numbers => month then day.
|
||
POP P,A
|
||
JRST ENGD4]
|
||
POP P,C ;A has month number, C has day number.
|
||
ENGD4: JUMPN C,ENGD5 ;If no day number, better DWIM.
|
||
CAIL A,32. ;Lone number is probably a day
|
||
JRST ENGDLZ ; else I give up.
|
||
DPB A,[TM$DAY,,(P)] ;Store day of month.
|
||
JRST ENGDOK
|
||
|
||
ENGD5: CAIG A,12. ;Examine month # for validity.
|
||
CAIL C,32. ;Bounds check the day number.
|
||
JRST ENGDLZ ; A loser - just return the number.
|
||
DPB C,[TM$DAY,,(P)] ;Else store them in time-word.
|
||
DPB A,[TM$MON,,(P)]
|
||
JRST ENGDYR ;Now go read the year.
|
||
|
||
|
||
;Read the time off the b.p. in D, returning time word with date=0 in A.
|
||
;Skips if it's valid. Leaves terminating char in B. Clobbers C.
|
||
ENGTIM: PUSHJ P,ENGTHM ;Read hours and minutes.
|
||
POPJ P,
|
||
ENGSEC: PUSH P,A ;Read seconds, adding them into time word in A.
|
||
JRST ENGTS0 ;return the sum.
|
||
|
||
;Read the time, as just hours and minutes, off the b.p. in D,
|
||
;returning time word in A.
|
||
;Skips if it's valid. Leaves terminating char in B. Clobbers C.
|
||
ENGTHM: PUSH P,[0]
|
||
ENGT0: MOVEI B,40
|
||
PUSHJ P,ENGTNM ;Read one number in decimal in A; C gets number of digits.
|
||
CAIGE C,3
|
||
JRST ENGT1 ;2 digits => it is just hours.
|
||
MOVE C,B
|
||
IDIVI A,100. ;else it is 24-hour hhmm. Take it apart.
|
||
EXCH C,B ;A has hours, C has minutes.
|
||
CAIL A,24.
|
||
JRST ENGTLZ
|
||
IMULI A,3600.*2 ;Stick hours into accumulator.
|
||
ADDM A,(P)
|
||
;Here with minutes in C; hours already in (p).
|
||
ENGT2: CAIL C,60.
|
||
JRST ENGTLZ
|
||
IMULI C,60.*2
|
||
ADDM C,(P)
|
||
JRST ENGTX ;Return the time word with hours and minutes.
|
||
|
||
ENGT1: CAIL A,24. ;here if first number is 1 or 2 digits:
|
||
JRST ENGTLZ
|
||
IMULI A,3600.*2 ;STore it as hours,
|
||
ADDM A,(P)
|
||
PUSHJ P,NUMINC ;and expect the minutes after a colon.
|
||
JRST ENGT2
|
||
|
||
;Read a decimal number off b.p. in D, returning it in A,
|
||
;and returning the number of digits in C.
|
||
;The terminating character is returned in B.
|
||
ENGTNM: SETZB A,C
|
||
PUSHJ P,NONSPC
|
||
ENGTN1: CAIL B,"0
|
||
CAILE B,"9
|
||
POPJ P,
|
||
IMULI A,10.
|
||
ADDI A,-"0(B)
|
||
ILDB B,D
|
||
AOJA C,ENGTN1
|
||
|
||
;Read the seconds off the b.p. in D, and add them into the time-word in (P).
|
||
;Then pop that into A and skip-return.
|
||
ENGTS0: PUSHJ P,NUMINC
|
||
CAIL C,60.
|
||
JRST ENGTLZ
|
||
LSH C,1
|
||
ADDM C,(P)
|
||
ENGTX: AOS -1(P)
|
||
PUSHJ P,NONSPC
|
||
ENGTLZ: POP P,A
|
||
POPJ P,
|
||
|
||
;Subroutines for input of month names.
|
||
|
||
;Read a month name off the b.p. in D. Skip if successful, with month number (origin 1) in A.
|
||
;No skip if there is no word (first nonspace is not a letter; leaves it in B).
|
||
;Err out to ENGDLZ if there is a word which is not recognized.
|
||
MONTH: PUSHJ P,LETTER
|
||
POPJ P, ;No skip if there is no word here (may be a number).
|
||
MOVE A,[-12.,,MONTAB+1]
|
||
PUSHJ P,WRD ;Read the rest of the word and look it up.
|
||
JRST ENGDLZ ;Unrecognized word must be invalid.
|
||
MOVEI A,-MONTAB(A) ;Get month number corresponding to word, from table pointer.
|
||
JRST MONTHX
|
||
|
||
;Advance to next nonspace, and skip if it's a letter.
|
||
LETTER: PUSHJ P,NONSPC
|
||
|
||
;Skip if character in B is a letter.
|
||
LETP: CAIG B,"Z+40
|
||
CAIGE B,"A+40
|
||
CAIG B,"Z
|
||
CAIGE B,"A
|
||
CAIA
|
||
MONTHX: AOS (P)
|
||
POPJ P,
|
||
|
||
NONSP1: ILDB B,D
|
||
|
||
;Advance to next nonspace; leave it in B. Assumes that next char is in B to start.
|
||
NONSPC: CAIE B,40
|
||
CAIN B,^I
|
||
JRST NONSP1
|
||
POPJ P,
|
||
|
||
;Advance over spaces and one "-" or "/". Leave next character in B.
|
||
NONSEP: PUSHJ P,NONSPC
|
||
CAIE B,"-
|
||
CAIN B,"/
|
||
JRST NONSP1
|
||
POPJ P,
|
||
|
||
;Search a table pointed to by the AOBJN in A
|
||
;for a word read off b.p. in D, starting with the character in B.
|
||
;Skip-returns an incremented aobjn pointer in A if word is found in the table.
|
||
;Else non-skip returns. In either case, the word terminator is left in B.
|
||
;Clobbers C.
|
||
;Somewhat specialized: no input word shorter than 3 characters matches.
|
||
;No input word longer than 15 characters is allowed at all.
|
||
WRD:
|
||
REPEAT 4,PUSH P,[0] ;Push 4 words to hold the string.
|
||
MOVEI C,-3(P)
|
||
HRLI C,170700 ;C points to middle of first word, leaving 2 chars of word for use.
|
||
;Note that we got at least 3 characters if C advances to the next word.
|
||
PUSH P,P ;Push a pointer to middle of last word, to check overflow.
|
||
HLLM C,(P)
|
||
;Store the character in B into the temporary storage, and advance to the next character.
|
||
WRD1: CAMN C,(P) ;Bomb out if word is too long.
|
||
JRST ENGDLZ
|
||
CAIL B,140 ;Convert lower case to upper.
|
||
SUBI B,40
|
||
IDPB B,C ;Store character on stack.
|
||
ILDB B,D ;Get next character of input.
|
||
PUSHJ P,LETP
|
||
TLZA C,-1
|
||
JRST WRD1 ;If it's a letter, store it too.
|
||
CAIN C,-4(P) ;Search fails if word read is shorter than 3 characters.
|
||
JRST WRDFL
|
||
MOVEI C,-4(P)
|
||
HRLI C,170700 ;Else reconstruct b.p. to beginning of word read,
|
||
PUSHJ P,WRD2 ;and compare against table entries one by one.
|
||
AOBJN A,.-1
|
||
SKIPGE A ;Found a match => skip. A points at entry that matched.
|
||
AOS -5(P)
|
||
WRDFL: SUB P,[5,,5]
|
||
POPJ P,
|
||
|
||
;Compare the string pointed to by a b.p. in C with the asciz string whose address
|
||
;is in the word which A points at. Skip if the first abbreviates the second.
|
||
;Clobbers no ACs.
|
||
WRD2: PUSH P,A
|
||
PUSH P,B
|
||
PUSH P,C
|
||
PUSH P,D
|
||
MOVE A,(A)
|
||
HRLI A,440700
|
||
WRD2A: ILDB B,A
|
||
ILDB D,C
|
||
JUMPE D,WRD2B
|
||
CAIN B,(D)
|
||
JRST WRD2A
|
||
CAIA
|
||
WRD2B: AOS -4(P)
|
||
POP P,D
|
||
POP P,C
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
] ;end ifn $$inf
|
||
|
||
IFN $$IN\$$INF,[ ;Subroutines for all time-input functions
|
||
|
||
;Read a number, but insist on skipping over a colon first.
|
||
NUMINC: CAIN B,40
|
||
JRST [ ILDB B,D ;Ignore leading spaces.
|
||
JRST NUMINC]
|
||
SETZ C,
|
||
CAIE B,": ;Return 0 if no colon to skip over.
|
||
POPJ P,
|
||
JRST NUMIN0
|
||
|
||
;Read a decimal number off b.p. in D, into C, stopping at a non-digit.
|
||
;Expects last character read to be in B. Starts with that char, but skips spaces.
|
||
NUMIN: CAIN B,40
|
||
JRST [ ILDB B,D ;Ignore leading spaces.
|
||
JRST NUMIN]
|
||
SETZ C,
|
||
NUMIN1: CAIL B,"0
|
||
CAILE B,"9 ;Terminate on non-digit.
|
||
POPJ P,
|
||
IMULI C,10.
|
||
ADDI C,-"0(B)
|
||
NUMIN0: ILDB B,D
|
||
JRST NUMIN1
|
||
] ;end ifn $$in\$$inf
|
||
|
||
IFN $$ABS,[ ;Routines for conversion to/from absolute days/seconds since year 1900.
|
||
|
||
; TIMADY - Time in Absolute Days. Converts time wd in A to absolute
|
||
; # of days since Jan 1 1900, returns value in same.
|
||
|
||
TIMADY: PUSH P,B
|
||
PUSH P,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,TIMAD1 ;Avoid screwing up for dates in 1900.
|
||
TRNE A,3 ;is this a leap yr?
|
||
; Note that 2000 is a leap year. We don't have to
|
||
; worry about -that- problem until 2100!
|
||
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)
|
||
TIMAD1: ADDI A,(C) ;plus days so far this yr
|
||
SOJA A,POPCBJ ; minus 1 since 1st day of month is day 1,
|
||
; (Don't ADDI A,-1(C) since C might be 0!)
|
||
|
||
; TIMSEC - Similar to TIMADY, but returns value in seconds.
|
||
; Value is 31,536,000. per yr (32 bits for 136 yrs).
|
||
|
||
TIMSEC: 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,
|
||
|
||
; TIMNET - Converts time word in A to 32-bit "Network time" in A.
|
||
|
||
TIMNET: PUSHJ P,TIMSEC ; Convert to network time.
|
||
ADDI A,ESTDIF*60.*60.
|
||
POPJ P, ; Return.
|
||
|
||
; TIMGTN - Similar to TIMNET, but uses the current time and skips for success.
|
||
; This is GMT in # seconds since 1/1/00.
|
||
|
||
TIMGTN: PUSH P,B
|
||
PUSH P,C
|
||
.RLPDTM A, ; Get in A, # secs since beg of year.
|
||
TLNN B,40000 ; in B, the year
|
||
JRST TIMGTX ; 4.6 => Time is known.
|
||
TLNE B,400000 ; 4.9 => past Feb 28 and non-leap-yr
|
||
SUBI A,24.*60.*60. ; so subtract one day from .RLPDTM misfeature.
|
||
TLNE B,100000 ; 4.7 => Daylight Savings time?
|
||
SUBI A,60.*60. ; 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,24.*60.*60. ; Now get # seconds in all them days.
|
||
ADD A,B ; and produce total seconds since 1/1/00 !
|
||
ADD A,[ESTDIF*60.*60.] ; Adjust to GMT.
|
||
AOS -2(P)
|
||
TIMGTX: POP P,C
|
||
POP P,B
|
||
POPJ P,
|
||
|
||
; ADYTIM - Convert Absolute Days to time word. Inverse of TIMADY.
|
||
; Takes # days since 1/1/1900 in A, returns time wd in same.
|
||
|
||
ADYTIM: PUSH P,B
|
||
PUSH P,C
|
||
IDIVI A,365. ;find # "normal" years.
|
||
JUMPE A,ADYTI1
|
||
MOVEI C,-1(A) ;now see how many leap years covered (not incl current)
|
||
LSH C,-2 ;divide by 4 to get # leap yrs
|
||
SUB 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]
|
||
|
||
ADYTI1: MOVEI C,12.
|
||
CAMGE B,TMONTB(C) ;compare # days in year with # days after each month
|
||
SOJA C,.-1 ;loop (#1 index has 0 value, so it will stop)
|
||
TRNN A,3 ;leap year?
|
||
JUMPN A,[
|
||
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,
|
||
ADDI 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
|
||
AOS B ;and day. Remember start of month is day 1, not day 0.
|
||
DPB B,[TM$DAY,,A]
|
||
HLLZS A ;Zap RH to start of day.
|
||
POPCBJ: POP P,C
|
||
POP P,B
|
||
POPJ P,
|
||
|
||
; Used to be called "TIMCAS".
|
||
; SECTIM - Converts Absolute Seconds to time word.
|
||
; Argument in A (# secs since 1/1/00), returns time wd in A.
|
||
|
||
SECTIM: PUSH P,B
|
||
IDIVI A,24.*60.*60. ; Get remainder of # secs in day
|
||
PUSHJ P,ADYTIM ; Find time wd given # days.
|
||
LSH B,1
|
||
ADD A,B ; Add in # half secs.
|
||
POPBJ: POP P,B
|
||
POPJ P,
|
||
|
||
; TIMADD - Add time in seconds in B to time word in A, returning time word in A.
|
||
|
||
TIMADD: PUSHJ P,TIMSEC
|
||
ADD A,B
|
||
JRST SECTIM
|
||
|
||
; TIMSUB - subtract time word in B from that in A,
|
||
; returning time difference in seconds in A.
|
||
|
||
TIMSUB: PUSH P,B
|
||
PUSHJ P,TIMSEC
|
||
EXCH A,B
|
||
PUSHJ P,TIMSEC
|
||
SUBM B,A
|
||
JRST POPBJ
|
||
|
||
; TIMDOW - Return in B the day-of-week (SUN = 0) of the time word in A.
|
||
|
||
TIMDOW: PUSH P,A
|
||
PUSHJ P,TIMADY
|
||
ADDI A,DWFUDG
|
||
IDIVI A,7
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
];$$ABS
|
||
|
||
|
||
;;; tables used in conversion between time words and absolute days.
|
||
|
||
; 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
|
||
|
||
IFN $$UPTM,[
|
||
|
||
; UPTIME - 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.
|
||
|
||
;Note: UPINI must be called before using this routine.
|
||
|
||
.SCALAR TMSYST ; Holds time of system startup in absolute # secs.
|
||
|
||
; *** This produces the wrong answer if daylight savings times went on or
|
||
; *** off since the system came up. Fix it some day!
|
||
|
||
UPTIME: PUSHJ P,TIMSEC ; Convert given time to absolute # secs.
|
||
SUB A,TMSYST ; Find difference in secs.
|
||
IMULI A,30. ; Turn into 30'ths.
|
||
POPJ P,
|
||
|
||
; UPINI - Initializes time routines and makes sure system knows the
|
||
; current time and time when came up; fails to skip if it doesn't.
|
||
|
||
UPINI: PUSH P,A ;Smash no ACs.
|
||
PUSH P,B
|
||
SYSCAL RQDATE,[%CLOUT,,B ? %CLOUT,,A]
|
||
SETO B,
|
||
CAME A,[-1] ;If we don't know when ITS came up
|
||
CAMN B,[-1] ; or know what time it is
|
||
JRST UPINI9 ; we lose.
|
||
PUSHJ P,TIMSEC ;Find uptime as abs secs since 1900.
|
||
MOVEM A,TMSYST ;Remember it.
|
||
AOS -2(P) ;Skip.
|
||
UPINI9: POP P,B ;Return.
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
] ;end ifn $$UPTM
|
||
|
||
|
||
IFN $$SVNG,[ ;Routines to handle daylight savings time.
|
||
|
||
;Note that the actual conversion is trivial: just use TIMADD to add +/- 3600. secs.
|
||
|
||
;Subroutine to skip if daylight saving time should not be
|
||
; applied to date being output converted.
|
||
;In other words, we have a date and a standard time,
|
||
; and we skip unless the user would rather see it printed in daylight time.
|
||
|
||
;To use, do
|
||
; MOVEI B,3600.
|
||
; PUSHJ P,DATIME"ODAYL ;If daylight time now in effect,
|
||
; PUSHJ P,TIMADD ;convert to daylight time before printing.
|
||
|
||
;This version puts daylight saving into effect at 2AM on the
|
||
;last Sunday in April and ends it at 1AM standard time on the
|
||
;last Sunday in October.
|
||
; It also includes forced daylight time from 6 JAN 74 thru summer 75.
|
||
|
||
;Takes a time-word in A.
|
||
|
||
ODAYL: PUSH P,A
|
||
PUSH P,B
|
||
PUSH P,C
|
||
PUSH P,D
|
||
HRRZ B,A
|
||
PUSHJ P,TIMADY ;B has just time, A has date as abs day number.
|
||
JSP D,DAYLFS ;CHECK DAYLIGHT FOR FUEL SHORTAGE
|
||
; WON'T RETURN HERE IF FORCED SETTING.
|
||
PUSH P,A
|
||
MOVE A,-4(P) ;Get time word back as arg for NMSS.
|
||
PUSHJ P,NMSS ;COMPUTE DATE OF MAGIC SUNDAY IN
|
||
POP P,A ;APRIL (MSAPR) INTO C AND DITTO OF OCT
|
||
;(MSOCT) INTO D.
|
||
CAMN A,D ;DATE = MSOCT?
|
||
CAIGE B,1*3600.*2 ;YES, 1AM OR AFTER STD TIME?
|
||
JRST .+2
|
||
JRST ODAYS ;YES AND YES, STD TIME APPLIES.
|
||
CAMN A,C ;DATE = MSAPR?
|
||
CAIL B,2*3600.*2 ;YES, BEFORE 2AM?
|
||
JRST .+2
|
||
JRST ODAYS ;YES AND YES, STD TIME.
|
||
;AT THIS POINT WE WOULD HAVE RETURNED IF IT WAS MSAPR OR
|
||
;MSOCT AND TIME OF DAY WAS SUCH THAT STANDARD TIME APPLIED.
|
||
;HENCE IF ITS BETWEEN MSAPR AND MSOCT INCLUSIVE,
|
||
;DAYLIGHT SAVING APPLIES.
|
||
CAML A,C ;DATE BEFORE MSAPR?
|
||
CAMLE A,D ;OR AFTER MSOCT?
|
||
JRST ODAYS ;YES, STANDARD TIME APPLIES.
|
||
JRST ODAYD
|
||
|
||
ODAYS: AOS -4(P) ;SKIP IF STANDARD TIME SHOULD BE USED
|
||
ODAYD: POP P,D
|
||
POP P,C
|
||
POP P,B
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
;Subroutine to skip UNLESS daylight saving time should
|
||
;be applied to date being input converted.
|
||
;IE, we have a time word of standard time or daylight time,
|
||
;and we SKIP if it should be treated as STANDARD time.
|
||
;If we skip, we leave the
|
||
|
||
;To use, do
|
||
; MOVNI B,3600.
|
||
; PUSHJ P,IDAYL ;If at a time when daylight time is in use,
|
||
; PUSHJ P,TIMADD ;convert daylight to standard.
|
||
|
||
IDAYL: PUSH P,A
|
||
PUSH P,B
|
||
MOVNI B,3600. ;Assuming it's daylight time, convert to standard,
|
||
PUSHJ P,TIMADD
|
||
POP P,B
|
||
PUSHJ P,ODAYL ;then see if the resulting standard time is a time at which
|
||
CAIA ;daylight savings was in effect.
|
||
AOS -1(P) ;Note: we don't screw up if it was really standard time
|
||
POP P,A ;because of the 1-hour gap when we move clock forward in APR.
|
||
POPJ P, ;Note also that there is no way to avoid ambiguity in OCT.
|
||
|
||
;SUBROUTINE TO CHECK FOR THE FORCED DAYLIGHT TIME DECLARED BY CONGRESS
|
||
; FOR THE FUEL SHORTAGE FROM 6 JAN 74 THRU THE SUMMER OF 74.
|
||
; ALSO, FOR THE MODIFICATION WHEREIN WE GO BACK TO DAYLIGHT
|
||
; TIME IN LATE FEBRUARY OF 75 RATHER THAN LATE APRIL. AS THE LAW
|
||
; STANDS TODAY, WE REVERT TO APRIL-OCTOBER IN 1976, AND THIS CODE
|
||
; DOES THAT, TOO, BUT WATCH YOUR LOCAL CONGRESSMAN....
|
||
|
||
;Call with JSP D,DAYLFS. It returns if it has no knowledge to contribute.
|
||
;If it knows whether daylight savings time was in effect then,
|
||
;It returns, skipping or not as appropriate, from its CALLER.
|
||
|
||
DSTFS1==64631 ;DAYLIGHT SAVINGS TIME, FUEL SHORTAGE, START
|
||
; DATE, WHICH IS 6 JAN 74 ( A SUNDAY ).
|
||
DSTFS2==65245 ;DAYLIGHT SAVINGS TIME, FUEL SHORTAGE, END
|
||
; DATE, WHICH IS 1 OCT 74, AND THE NORMAL
|
||
; ALGORITHM TAKES OVER FOR REST OF THAT MONTH.
|
||
DSTFS3==65466 ;23 FEB 75, WHEN WE GO BACK TO DAYLIGHT TIME
|
||
; EARLY FOR SUMMER 75.
|
||
DSTFS4==65571 ;1 MAY 75, WHEN THE NORMAL ALGORITHM TAKES OVER
|
||
; AGAIN UNTIL THE LAW CHANGES AGAIN.
|
||
|
||
DAYLFS: CAIN A,DSTFS1 ;The day this period starts?
|
||
CAIL B,2*3600.*2 ;Yes. Before 2 AM standard time?
|
||
SKIPA ;Not morning of that day.
|
||
JRST ODAYS ;Yes. First hours of that day. std time.
|
||
CAIGE A,DSTFS1 ;Any time in this fudged period?
|
||
JRST 0(D) ;Before 6 JAN 74. Normal algorithm.
|
||
CAIGE A,DSTFS2 ; ..
|
||
JRST ODAYD ;Yes. Force daylight time.
|
||
CAIN A,DSTFS3 ;23 FEB 75, first day of DST in 75?
|
||
CAIL B,2*3600.*2 ;Yes. Before 2 AM?
|
||
SKIPA ;No.
|
||
JRST ODAYS ;Yes. Still standard time.
|
||
CAIL A,DSTFS3 ;In the period 23 FEB 75 0200 thru
|
||
CAIL A,DSTFS4 ;1 MAY 75?
|
||
JRST 0(D) ;No. Use normal algorithm.
|
||
JRST ODAYD ;Yes. This is forced daylight time.
|
||
|
||
; Compute dates of magic Sundays in April and October in C, D as absolute day
|
||
; numbers.
|
||
;
|
||
; Prior to 1987 the magic Sundays were the last Sundays in April and
|
||
; October. In 1987 the law was changed so that the first day of daylight
|
||
; savings time fell on the -first- Sunday in April. The date to switch
|
||
; back remained the last Sunday in October.
|
||
;
|
||
; Takes a date to use the year from as a time word in A.
|
||
|
||
NMSS: PUSH P,A
|
||
AND A,[TM%YR] ;Flush all of supplied date except year.
|
||
PUSH P,A
|
||
CAMGE A,[.DPB 87.,TM$YR,0]
|
||
TLOA A,(.DPB 4,TM$MON,.DPB 30.,TM$DAY,0)
|
||
TLO A,(.DPB 4,TM$MON,.DPB 7,TM$DAY,0)
|
||
PUSHJ P,TIMADY ;Get absolute day number of 30th day April
|
||
; of year in A.
|
||
;Date of magic Sunday in April this year (MSAPR) to C
|
||
;Have date of APR 7 or APR 30 this year =last possible date of magic Sunday
|
||
;in April. If it isn't Sunday, find preceding Sunday.
|
||
MOVE C,A
|
||
ADDI C,DWFUDG+70000. ;Add 70000 to make sure its positive.
|
||
IDIVI C,7 ;Divide into weeks and day of weeks
|
||
IMULI C,7 ;Convert back, discarding day of week
|
||
SUBI C,DWFUDG+70000. ;Unfudge and we've got it!
|
||
;DATE OF MAGIC SUNDAY IN OCTOBER (MSOCT) THIS YEAR TO D.
|
||
POP P,A
|
||
TLO A,(.DPB 10.,TM$MON,<.DPB 31.,TM$DAY,0>)
|
||
PUSHJ P,TIMADY ;Get day # of oct 31 of this year.
|
||
PUSH P,E
|
||
MOVE D,A
|
||
ADDI D,DWFUDG+70000.
|
||
IDIVI D,7
|
||
IMULI D,7
|
||
SUBI D,DWFUDG+70000.
|
||
POP P,E
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
] ;end ifn $$SVNG
|
||
|
||
.END DATIME
|