mac-rom/Toolbox/SexyDate.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

225 lines
6.5 KiB
Plaintext

;EASE$$$ READ ONLY COPY of file Òsexydate.aÓ
; 1.1 CCH 11/10/1988 Fixed Header.
; 1.0 CCH 11/ 9/1988 Adding to EASE.
; OLD REVISIONS BELOW
; 1.0 BBM 2/11/88 Adding file for the first time into EASEÉ
; END EASE MODIFICATION HISTORY
; File SexyDate.TEXT
;
; Routines to convert between number of seconds elapsed since 1904 Jan 1 00:00:00 am
; and date: year / month / day / hour / min / sec / (day of week).
; Written by Jerome T. Coonen 2 July 1983
;
; Seconds: unsigned 32-bit integer passed in D0.
;
; Date: array of 7 16-bit integers pointed to by A0.
; 0: year -- 1904, 1905, ...
; 1: month -- 1, 2, ..., 12
; 2: day -- 1, 2, ..., 31
; 3: hour -- 0, 1, ..., 24
; 4: minute -- 0, 1, ..., 59
; 5: second -- 0, 1, ..., 59
; 6: weekday -- 1, 2, ..., 7 corresponding to Sun, Mon, ..., Sat
;
BLANKS ON
STRING ASIS
SEXYDATE PROC EXPORT
EXPORT SECS2DATE, DATE2SECS
SECS2DATE
MOVEM.L D0-D4/A0,-(SP) ; SAVE WORKING REGISTERS
;
; Have number of seconds N 1904 in D0. Compute
; DN = number of days elapsed = N div 86400 where 86400 = 24 * 60 * 60
; HMS = number of seconds in last day = N mod 86400.
; Since 86400 > 2^31-1 cannot use 68000 DIVU directly. Instead, divide halved number
; of seconds by 43200. To get HMS, must double computed mod (with 43200) and add in the
; low order bit of the input N.
;
MOVEQ #0,D1 ; INIT HMS
LSR.L #1,D0 ; N DIV 2, WITH ODD BIT TO X
ROXR.L #1,D1 ; GET X BIT IN HI SLOT, FOR LATER ROTATE
DIVU #43200,D0
SWAP D0 ; GET MOD 43200 IN D0.W
MOVE.W D0,D1 ; HALF THE MOD IN D1.W
ROL.L #1,D1
CLR.W D0 ; WANT LONG DN
SWAP D0 ; DN
;
; YearsGone = (DN * 4) div 1461 where 1461 is 4*365+1
; Formula depends on leap year being the first of the four.
;
MOVE.L D0,D2 ; COPY DN
ASL.L #2,D2 ; DN * 4
DIVU #1461,D2 ; YEARSGONE = (DN * 4) DIV 1461
ADDI.W #1904,D2 ; YEAR
MOVE.W D2,(A0)+
;
; Need number of days in Jan+Feb just below. So take YEAR mod 3 before clearing year.
;
MOVEQ #59,D3 ; ASSUME NOT LEAP YEAR
ANDI.W #3,D2 ; YEAR MOD 3
BNE.S SDNOTLEAP
ADDQ.W #1,D3
SDNOTLEAP
CLR.W D2 ; LEAVE 4 * DOY = DAY OF YEAR IN HI WORD
SWAP D2
LSR.W #2,D2 ; D0Y
;
; Computing Month/Day from DOY is an exercise in interpolation. As a function of DOY,
; MONTH is a step function. Because of the leap year glitch, convenient to restart
; function at March.
;
; DOY MONTH
;-------------------------------------------------------------------
; 0-30 1 -- January
; 31-58/59 2 -- February (depends on whether leap year)
;
; 0-30 3 -- March
; 31-60 4 -- April
; 61-91 5 -- May
; 92-121 6 -- June
; 122-152 7 -- July
; 153-183 8 -- August
; 184-213 9 -- September
; 214-244 10 -- October
; 244-274 11 -- November
; 275-305 12 -- December
;
; The linear interpolator is ((DOY * 128) + 71) div 3919.
;
MOVEQ #1,D4 ; MONTH OFFSET, 1 OR 3
CMP.W D3,D2 ; 59/60 VERSUS DOY
BLT.S SDJANORFEB ; LESS THAN MEANS JAN OR FEB
ADDQ.W #2,D4 ; ADJUST MONTH OFFSET
SUB.W D3,D2 ; START DOY AT MARCH
SDJANORFEB
LSL.L #7,D2 ; DOY * 128
MOVEQ #71,D3
ADD.L D3,D2 ; (DOY * 128) + 71
DIVU #3919,D2 ; ((DOY * 128) + 71) DIV 3919
ADD.W D4,D2 ; ADJUST MONTH 1..12
SWAP D2 ; HAVE MONTH | DAY-1
LSR.W #7,D2 ; DIVIDE BY 128 TO GET DAY OF MONTH
ADDQ.W #1,D2 ; DAY 1..31
MOVE.L D2,(A0)+
;
; HOURS = HMS div 3600
; MS = HMS mod 3600 = minutes/seconds
; MINUTES = MS div 60
; SECONDS = MS mod 60
;
DIVU #3600,D1 ; HMS DIV 3600
MOVE.W D1,(A0)+ ; HOURS
CLR.W D1
SWAP D1 ; MS
DIVU #60,D1 ; SECONDS | MINUTES
SWAP D1
MOVE.L D1,(A0)+ ; MINUTES | SECONDS
;
; Finally get the day of week = ((DN + 5) mod 7) + 1
; The 5 is added since 1 Jan 1904 was a Friday.
;
ADDQ.W #5,D0
DIVU #7,D0
SWAP D0
ADDQ.W #1,D0
MOVE.W D0,(A0)
;
; Clean up stack and return.
;
MOVEM.L (SP)+,D0-D4/A0
RTS
;
; Have year / month / day / hours / min / sec in a sequence of words pointed to by A0.
; Deduce number of seconds since 1904, and return in D0.
;
; Since a date is no more than a representation of time in a bizarre mixed radix,
; the computation reduces to:
; DAYSGONE * 86400 + HOURS * 3600 + MINUTES * 60 + SECONDS
; The hard part is deducing the DAYSGONE from the YEAR / MONTH / DAY.
;
DATE2SECS
MOVEM.L D1-D4,-(SP) ; WORKING REGISTERS
;
; Do the easy part with HOURS, MINUTES, and SECONDS.
;
MOVEQ #0,D0 ; INIT SECOND COUNT
ADDQ.L #8,A0 ; POINT TO MINUTES/SECONDS
MOVE.L (A0),D1 ; MINUTES | SECONDS
MOVE.W D1,D0 ; SECONDS
SWAP D1 ; MINUTES
MOVE.W -(A0),D2 ; HOURS
MOVEQ #60,D3
MULU D3,D2 ; HOURS * 60
ADD.W D1,D2 ; (HOURS * 60) + MINUTES
MULU D3,D2 ; ((HOURS * 60) + MINUTES) * 60
ADD.L D2,D0
;
; Compute DAYSGONE in D1.
;
MOVE.W -(A0),D1 ; DAYS
SUBQ.W #1,D1
MOVE.W -(A0),D2 ; MONTH
MOVE.W -(A0),D3 ; YEAR, AND A0 IS BACK TO INPUT VALUE
MOVE.W D3,D4 ; COPY YEAR FOR LEAP TEST
;
; To find number of days in elapsed years use ((YEARSGONE * 1461) + 3) div 4.
; Formula depends on leap year being the first of a quartet.
;
SUBI.W #1904,D3 ; YEARSGONE
MULU #1461,D3 ; YEARSGONE * 1461
ADDQ.L #3,D3 ; (YEARSGONE * 1461) + 3
LSR.L #2,D3 ; ((YEARSGONE * 1461) + 3) DIV 4
ADD.W D3,D1 ; ACCUMULATE DAYSGONE
;
; As above, the tough part is finding the number of days in the elapsed months.
; The function to be interpolated is in a sense the inverse of the step function above.
; The interpolating function is ((MONTHSGONE * 3917) + 52) div 128.
;
SUBQ.W #1,D2 ; MONTH-1 RANGES 0..11
CMPI.W #1,D2 ; 2 OR MORE IS MARCH...
BLE.S DSJANORFEB
SUBQ.W #2,D2 ; MONTH-3, RESTART INTERP AT MARCH
MOVEQ #59,D3 ; DAYS IN JAN AND FEB
ANDI.W #3,D4 ; CHECK FOR LEAP YEAR, MOD 3
BNE.S DSNOTLEAP
ADDQ.W #1,D3
DSNOTLEAP
ADD.W D3,D1 ; SOME MORE ELAPSED DAYS
DSJANORFEB
MULU #3917,D2 ; (MONTHSGONE * 3917)
ADDI.W #52,D2 ; (MONTHSGONE * 3917) + 52
LSR.W #7,D2 ; ((MONTHSGONE * 3917) + 52) DIV 128
ADD.W D2,D1 ; MORE ELAPSED DAYS
;
; Finally multiply the number of days elapsed by 24*60*60 = 86400 = 43200*2
;
MULU #43200,D1
ADD.L D1,D1
ADD.L D1,D0
MOVEM.L (SP)+,D1-D4
RTS
END