.TITLE TERVEHDYS
.IDENT /V1.4/
.LIBRARY /SYS$LIBRARY:STARLET.MLB/
$SSDEF
$DSCDEF
.PSECT DATA,NOEXE,WRT,LONG
UTC_TIME: .BLKQ 1
UTCNUM: .BLKW 7
FINNUM: .BLKW 7
DAY: .BLKL 1
YEAR: .BLKL 1
HOUR: .BLKL 1
MINUTE: .BLKL 1
SECOND: .BLKL 1
MAR_LAST: .BLKL 1
OCT_LAST: .BLKL 1
MONTH_PTR: .BLKL 1
OFFSET_HOURS: .BLKL 1
MONTH_LEN: .BLKL 1
OUTBUF: .BLKB 132
OUTLEN: .BLKW 1
OUT_DSC:
.WORD 132
.BYTE DSC$K_DTYPE_T
.BYTE DSC$K_CLASS_S
.ADDRESS OUTBUF
FMT_DATE: .ASCID /!UL. !AS !UL !2ZL:!2ZL:!2ZL Suomen aikaa/
MON01: .ASCID /tammikuuta/
MON02: .ASCID /helmikuuta/
MON03: .ASCID /maaliskuuta/
MON04: .ASCID /huhtikuuta/
MON05: .ASCID /toukokuuta/
MON06: .ASCID /kesakuuta/
MON07: .ASCID /heinakuuta/
MON08: .ASCID /elokuuta/
MON09: .ASCID /syyskuuta/
MON10: .ASCID /lokakuuta/
MON11: .ASCID /marraskuuta/
MON12: .ASCID /joulukuuta/
MONTH_TABLE:
.ADDRESS MON01,MON02,MON03,MON04,MON05,MON06
.ADDRESS MON07,MON08,MON09,MON10,MON11,MON12
MDAYS:
.LONG 31,28,31,30,31,30,31,31,30,31,30,31
MSG_TIME: .ASCID /Paivamaara ja aika:/
GREET_MORN: .ASCID /Hyvaa huomenta!/
GREET_DAY: .ASCID /Hyvaa paivaa!/
GREET_EVE: .ASCID /Hyvaa iltaa!/
GREET_NIGHT: .ASCID /Hyvaa yota!/
.PSECT CODE,EXE,NOWRT,LONG
.ENTRY START,^M<>
$GETTIM_S TIMADR=UTC_TIME
BLBS R0,10$
JMP ERROR
10$:
$NUMTIM_S TIMBUF=UTCNUM,TIMADR=UTC_TIME
BLBS R0,20$
JMP ERROR
20$:
; Find last Sunday of March and October in the UTC year.
MOVZWL UTCNUM+0,R0
MOVL #3,R1
MOVL #31,R2
BSBW LAST_SUNDAY
MOVL R0,MAR_LAST
MOVZWL UTCNUM+0,R0
MOVL #10,R1
MOVL #31,R2
BSBW LAST_SUNDAY
MOVL R0,OCT_LAST
; Default: Finnish winter time, UTC+2.
MOVL #2,OFFSET_HOURS
; Finnish summer time: last Sunday of March 01:00 UTC
; through last Sunday of October before 01:00 UTC.
MOVZWL UTCNUM+2,R0 ; UTC month
CMPL R0,#3
BLSS HAVE_OFFSET ; Jan-Feb
CMPL R0,#10
BGTR HAVE_OFFSET ; Nov-Dec
CMPL R0,#3
BEQL CHECK_MARCH
CMPL R0,#10
BEQL CHECK_OCTOBER
MOVL #3,OFFSET_HOURS ; Apr-Sep
BRW HAVE_OFFSET
CHECK_MARCH:
MOVZWL UTCNUM+4,R0 ; UTC day
CMPL R0,MAR_LAST
BLSS HAVE_OFFSET
BGTR MARCH_DST
MOVZWL UTCNUM+6,R0 ; UTC hour
CMPL R0,#1
BLSS HAVE_OFFSET
MARCH_DST:
MOVL #3,OFFSET_HOURS
BRW HAVE_OFFSET
CHECK_OCTOBER:
MOVL #3,OFFSET_HOURS ; October is DST until cutoff
MOVZWL UTCNUM+4,R0
CMPL R0,OCT_LAST
BLSS HAVE_OFFSET
BGTR OCT_STD
MOVZWL UTCNUM+6,R0
CMPL R0,#1
BLSS HAVE_OFFSET
OCT_STD:
MOVL #2,OFFSET_HOURS
HAVE_OFFSET:
; Copy UTC numeric time to FINNUM.
MOVW UTCNUM+0,FINNUM+0
MOVW UTCNUM+2,FINNUM+2
MOVW UTCNUM+4,FINNUM+4
MOVW UTCNUM+6,FINNUM+6
MOVW UTCNUM+8,FINNUM+8
MOVW UTCNUM+10,FINNUM+10
MOVW UTCNUM+12,FINNUM+12
; Add 2 or 3 hours.
MOVZWL FINNUM+6,R0
ADDL2 OFFSET_HOURS,R0
CMPL R0,#24
BLSS STORE_HOUR
SUBL2 #24,R0
MOVW R0,FINNUM+6
BSBW INC_DATE
BRW AFTER_HOUR
STORE_HOUR:
MOVW R0,FINNUM+6
AFTER_HOUR:
MOVZWL FINNUM+0,YEAR
MOVZWL FINNUM+4,DAY
MOVZWL FINNUM+6,HOUR
MOVZWL FINNUM+8,MINUTE
MOVZWL FINNUM+10,SECOND
MOVZWL FINNUM+2,R1
DECL R1
MULL2 #4,R1
MOVL MONTH_TABLE(R1),MONTH_PTR
PUSHL SECOND
PUSHL MINUTE
PUSHL HOUR
PUSHL YEAR
PUSHL MONTH_PTR
PUSHL DAY
PUSHAQ OUT_DSC
PUSHAL OUTLEN
PUSHAQ FMT_DATE
CALLS #9,G^LIB$SYS_FAO
BLBS R0,30$
JMP ERROR
30$:
MOVW OUTLEN,OUT_DSC
PUSHAQ MSG_TIME
CALLS #1,G^LIB$PUT_OUTPUT
PUSHAQ OUT_DSC
CALLS #1,G^LIB$PUT_OUTPUT
CMPW FINNUM+6,#6
BLSS SAY_NIGHT
CMPW FINNUM+6,#12
BLSS SAY_MORN
CMPW FINNUM+6,#18
BLSS SAY_DAY
CMPW FINNUM+6,#22
BLSS SAY_EVE
SAY_NIGHT:
PUSHAQ GREET_NIGHT
BRB PRINT_GREET
SAY_MORN:
PUSHAQ GREET_MORN
BRB PRINT_GREET
SAY_DAY:
PUSHAQ GREET_DAY
BRB PRINT_GREET
SAY_EVE:
PUSHAQ GREET_EVE
PRINT_GREET:
CALLS #1,G^LIB$PUT_OUTPUT
MOVL #SS$_NORMAL,R0
RET
ERROR:
PUSHL R0
CALLS #1,G^LIB$STOP
RET
; Increment FINNUM date by one day.
INC_DATE:
MOVZWL FINNUM+0,R0 ; year
MOVZWL FINNUM+2,R1 ; month
BSBW GET_MONTH_LENGTH
MOVL R0,MONTH_LEN
MOVZWL FINNUM+4,R0 ; day
INCL R0
CMPL R0,MONTH_LEN
BGTR NEXT_MONTH
MOVW R0,FINNUM+4
RSB
NEXT_MONTH:
MOVW #1,FINNUM+4
MOVZWL FINNUM+2,R0
INCL R0
CMPL R0,#12
BGTR NEXT_YEAR
MOVW R0,FINNUM+2
RSB
NEXT_YEAR:
MOVW #1,FINNUM+2
MOVZWL FINNUM+0,R0
INCL R0
MOVW R0,FINNUM+0
RSB
; Input:
; R0 = year
; R1 = month
; Output:
; R0 = length of month
GET_MONTH_LENGTH:
DECL R1
MULL2 #4,R1
MOVL MDAYS(R1),R2
; February: check leap year.
CMPL R1,#4 ; original month 2 -> index 1 -> offset 4
BNEQ MONTH_LEN_DONE
BSBW IS_LEAP
TSTL R0
BEQL MONTH_LEN_DONE
MOVL #29,R2
MONTH_LEN_DONE:
MOVL R2,R0
RSB
; Input:
; R0 = year
; Output:
; R0 = 1 if leap year, 0 otherwise
IS_LEAP:
MOVL R0,R3
MOVL R3,R4
DIVL2 #400,R4
MULL2 #400,R4
CMPL R3,R4
BEQL LEAP_YES
MOVL R3,R4
DIVL2 #100,R4
MULL2 #100,R4
CMPL R3,R4
BEQL LEAP_NO
MOVL R3,R4
DIVL2 #4,R4
MULL2 #4,R4
CMPL R3,R4
BEQL LEAP_YES
LEAP_NO:
CLRL R0
RSB
LEAP_YES:
MOVL #1,R0
RSB
; Input:
; R0 = year
; R1 = month, 3 or 10
; R2 = last day of month
; Output:
; R0 = day number of last Sunday in that month
LAST_SUNDAY:
MOVL R0,R3
MOVL R1,R4
MOVL R2,R5
ADDL3 #1,R4,R6
MULL2 #13,R6
DIVL2 #5,R6
ADDL3 R5,R6,R7
ADDL2 R3,R7
MOVL R3,R8
DIVL2 #4,R8
ADDL2 R8,R7
MOVL R3,R8
DIVL2 #100,R8
SUBL2 R8,R7
MOVL R3,R8
DIVL2 #400,R8
ADDL2 R8,R7
MOVL R7,R8
DIVL2 #7,R8
MULL2 #7,R8
SUBL2 R8,R7
ADDL2 #6,R7
MOVL R7,R8
DIVL2 #7,R8
MULL2 #7,R8
SUBL2 R8,R7
SUBL3 R7,R5,R0
RSB
.END START
Comments
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎