1
0
mirror of https://github.com/PDP-10/its.git synced 2026-01-14 23:55:40 +00:00
2018-07-27 23:36:38 +01:00

695 lines
20 KiB
Common Lisp
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; -*- Package:TIME; Mode:Lisp; -*-
;;;
;;; This package created by KMP@MC, 24 May 81.
;;;
;;; TIME:DAYS - Bound to an alist of (daynum . dayname)
;;; TIME:MONTHS - Bound to an alist of (monthnum . monthname)
;;;
;;; STANDARD-OUTPUT - If undefined when this package loads, this variable
;;; will be set to the current value of TYO
;;;
;;; (TIME:GET-TIME-LIST)
;;; Returns (sec mins hours date month year dayofweek). This returns
;;; information similar to that returned by the LispM TIME:GET-TIME
;;; routine, but the information is returned as a list.
;;; Unlike the LispM, however, dayofweek is returned as a string (not
;;; a fixnum) and daylightsavings information is not returned at all.
;;;
;;; (TIME:PARSE-LIST string)
;;; Returns (sec mins hours date month year dayofweek). This returns
;;; information similar to that returned by the LispM TIME:PARSE
;;; routine, but the information is returned as a list.
;;; Unlike the LispM, however, dayofweek is returned as a string (not
;;; a fixnum). Daylightsavings information and relative information
;;; is not returned at all.
;;;
;;; The following several functions are used the same as in LispM lisp.
;;; The optional argument, stream, in the following functions defaults to
;;; the value of the symbol STANDARD-OUTPUT. A stream argument of () means
;;; to return the string rather than printing it.
;;; Year arguments less than one hundred are assumed to be offset from
;;; 1900.
;;; Day of week arguments to the dateprinting functions may be either
;;; strings or fixnums (0=Monday).
;;;
;;; (TIME:PRINT-CURRENT-TIME &optional stream)
;;; Calls TIME:PRINT-TIME using the current time.
;;;
;;; (TIME:PRINT-TIME sec min hrs date month year &optional stream)
;;; Displays the given time in format yr/mo/dy hr:min:sec
;;;
;;; (TIME:PRINT-CURRENT-DATE &optional stream)
;;; Calls TIME:PRINT-DATE using the current date.
;;;
;;; (TIME:PRINT-DATE sec min hrs date month year dayofweek &optional stream)
;;; Displays the given time in full English format. eg,
;;; Sunday the twenty-fourth of May; 3:02:17 pm
;;;
;;; (TIME:MONTH-STRING n &optional ignore)
;;; Returns the name of the nth month (1=January).
;;; Mode is not supported but is provided for calling compatibility
;;; with the LispM.
;;;
;;; (TIME:DAY-OF-THE-WEEK-STRING n &optional ignore)
;;; Returns the name of the nth day of the week (0=Monday).
;;; Mode is not supported but is provided for calling compatibility
;;; with the LispM.
;;;
;;; (TIME:VERIFY-DATE date month year dayofweek)
;;; Returns () if day,month,year fell on dayofweek. Else returns a string
;;; containing a suitable error message.
;;;
;;; This last function is not in the LispM lisp time package, but seemed
;;; a useful function to have, so is provided at no extra cost.
;;;
;;; (TIME:ON-WHAT-DAY-OF-THE-WEEK? day month year)
;;; Returns the day of the week that a given day fell on.
;;;
#+Maclisp
(HERALD TIME)
#+Maclisp
(DEFVAR STANDARD-OUTPUT TYO)
#+Maclisp
(EVAL-WHEN (COMPILE) (SETQ DEFMACRO-FOR-COMPILING ()))
#+Maclisp
(DEFMACRO CHAR-UPCASE (X)
(IF (NOT (ATOM X))
`(LET ((X ,X)) (CHAR-UPCASE X))
`(IF (AND (>= ,X #/a) (<= ,X #/z))
(- ,X #.(- #/a #/A))
,X)))
#+Maclisp
(DEFMACRO CHAR-DOWNCASE (X)
(IF (NOT (ATOM X))
`(LET ((X ,X)) (CHAR-DOWNCASE X))
`(IF (AND (>= ,X #/A) (<= ,X #/Z))
(- ,X #.(- #/A #/a))
,X)))
(DEFMACRO STANDARDIZE-YEAR (YEAR)
(IF (NOT (ATOM YEAR))
`(LET ((YEAR ,YEAR)) (STANDARDIZE-YEAR YEAR))
`(IF (< ,YEAR 100.) (+ ,YEAR 1900.) ,YEAR)))
(DEFMACRO STRING-UPPERCASE-INITIAL (FORM)
`(LET ((EXPL (EXPLODEN ,FORM)))
(IMPLODE (CONS (CHAR-UPCASE (CAR EXPL))
(DO ((L (CDR EXPL) (CDR L))
(LL () (CONS (CHAR-DOWNCASE (CAR L)) LL)))
((NULL L) (NREVERSE LL)))))))
(DEFMACRO DAY (X) `(CDR (ASSQ ,X TIME:DAYS)))
(DEFVAR TIME:DAYS
'((0. . "Monday" )
(1. . "Tuesday" )
(2. . "Wednesday")
(3. . "Thursday" )
(4. . "Friday" )
(5. . "Saturday" )
(6. . "Sunday" )))
(DEFMACRO MONTH (X) `(CDR (ASSQ ,X TIME:MONTHS)))
(DEFVAR TIME:MONTHS
'((1. . "January" )
(2. . "February" )
(3. . "March" )
(4. . "April" )
(5. . "May" )
(6. . "June" )
(7. . "July" )
(8. . "August" )
(9. . "September")
(10. . "October" )
(11. . "November" )
(12. . "December" )))
(DEFUN TIME:GET-TIME-LIST ()
(LET ((FULL-DATE (STATUS DATE))
(FULL-TIME (STATUS DAYTIME))
(DAY-OF-WEEK (STATUS DOW)))
(IF (NOT (EQUAL FULL-DATE (STATUS DATE)))
(TIME:GET-TIME-LIST)
(LET (((HOURS MINUTES SECONDS) FULL-TIME)
((YEAR MONTH DATE ) FULL-DATE)
(DOW (STRING-UPPERCASE-INITIAL DAY-OF-WEEK)))
(LIST SECONDS MINUTES HOURS DATE MONTH YEAR DOW)))))
(DEFUN TIME:PRINT-CURRENT-TIME (&OPTIONAL (STREAM STANDARD-OUTPUT))
(LEXPR-FUNCALL #'TIME:PRINT-TIME
(NREVERSE
(CONS STREAM (CDR (REVERSE (TIME:GET-TIME-LIST)))))))
(DEFUN TIME:PRINT-TIME (SECONDS MINUTES HOURS DATE MONTH YEAR
&OPTIONAL (STREAM STANDARD-OUTPUT))
(SETQ YEAR (STANDARDIZE-YEAR YEAR))
(FORMAT STREAM "~D//~D//~D ~D:~2,'0D:~2,'0D"
MONTH
DATE
YEAR
HOURS
MINUTES
SECONDS))
(DEFUN TIME:PRINT-CURRENT-DATE (&OPTIONAL (STREAM STANDARD-OUTPUT))
(LEXPR-FUNCALL #'TIME:PRINT-DATE
(APPEND (TIME:GET-TIME-LIST) (NCONS STREAM))))
(DEFUN TIME:PRINT-DATE (SECONDS MINUTES HOURS DATE MONTH YEAR DAY-OF-WEEK
&OPTIONAL (STREAM STANDARD-OUTPUT))
(SETQ YEAR (STANDARDIZE-YEAR YEAR))
(LET ((MSG (TIME:VERIFY-DATE DATE MONTH YEAR DAY-OF-WEEK)))
(IF MSG (FERROR NIL MSG)))
(FORMAT STREAM "~A the ~:R of ~A, ~D; ~D:~2,'0D:~2,'0D ~A"
(IF (FIXP DAY-OF-WEEK)
(DAY DAY-OF-WEEK)
(STRING-UPPERCASE-INITIAL DAY-OF-WEEK))
DATE
(MONTH MONTH)
YEAR
(LET ((HR (\ HOURS 12.))) (IF (ZEROP HR) 12. HR))
MINUTES
SECONDS
(IF (ZEROP (// HOURS 12.)) "am" "pm")))
(DEFUN TIME:MONTH-STRING (MONTHNUM &OPTIONAL MODE) MODE ;ignored
(MONTH MONTHNUM))
(DEFUN TIME:DAY-OF-THE-WEEK-STRING (DAYNUM &OPTIONAL MODE) MODE ;ignored
(DAY DAYNUM))
(DEFUN TIME:VERIFY-DATE (DATE MONTH YEAR DAY-OF-THE-WEEK)
(SETQ YEAR (STANDARDIZE-YEAR YEAR))
(LET ((TRUE-DOW (TIME:DAY-OF-THE-WEEK-STRING
(TIME:ON-WHAT-DAY-OF-THE-WEEK? DATE MONTH YEAR))))
(IF (FIXP DAY-OF-THE-WEEK)
(SETQ DAY-OF-THE-WEEK (TIME:DAY-OF-THE-WEEK-STRING DAY-OF-THE-WEEK)))
(SETQ DAY-OF-THE-WEEK (STRING-UPPERCASE-INITIAL DAY-OF-THE-WEEK))
(IF (NOT (SAMEPNAMEP DAY-OF-THE-WEEK TRUE-DOW))
(LET (((TODAY-DATE TODAY-MONTH TODAY-YEAR)
(CDDDR (TIME:GET-TIME-LIST))))
(SETQ TODAY-YEAR (STANDARDIZE-YEAR TODAY-YEAR))
(FORMAT ()
(COND ((OR (> TODAY-YEAR YEAR)
(AND (= TODAY-YEAR YEAR)
(OR (> TODAY-MONTH MONTH)
(AND (= TODAY-MONTH MONTH)
(> TODAY-DATE DATE)))))
"The ~:R of ~A, ~D fell on a ~A, not a ~A.")
((AND (= TODAY-YEAR YEAR)
(= TODAY-MONTH MONTH)
(= TODAY-DATE DATE))
"Today is a ~3G~A, not a ~A.")
(T
"The ~:R of ~A, ~D will fall on a ~A, not a ~A."))
DATE
(MONTH MONTH)
YEAR
TRUE-DOW
DAY-OF-THE-WEEK)))))
;;; This code adapted from JONL's package MC:LIBDOC;DOW >
;;; The following function, when given the date as three numbers,
;;; will produce a number of the day-of-week for that date (0=Monday).
;;; eg,
;;; (TIME:DAY-OF-THE-WEEK-STRING
;;; (TIME:ON-WHAT-DAY-OF-THE-WEEK? 22. 11. 1963.))
;;; => "Friday"
;;; which happened to be the day President John F. Kennedy was assasinated.
(DEFUN TIME:ON-WHAT-DAY-OF-THE-WEEK? (DAY MONTH YEAR)
(IF (NOT (AND (FIXP YEAR) (FIXP MONTH) (FIXP DAY)))
(ERROR "Args to TIME:DAY-OF-WEEK must be fixnums" (LIST YEAR MONTH DAY))
(SETQ YEAR (STANDARDIZE-YEAR YEAR))
(LET ((A (+ YEAR (// (+ MONTH -14.) 12.))))
(DECLARE (FIXNUM A))
(\ (+ (// (1- (* 13. (+ MONTH 10. (* (// (+ MONTH 10.) -13.) 12.))))
5.)
DAY
76.
(// (* 5. (- A (* (// A 100.) 100.))) 4.)
;; ejs: commented out as per Alan Sampson. This is an incorrect
;; check.
;; (// A -2000.)
(// A 400.)
(* (// A -100.) 2.))
7.))))
;;; The following sequence is translated from the Teco code in
;;; KMP's TPARSE library.
(EVAL-WHEN (EVAL COMPILE)
(COND ((NOT (GET 'UMLMAC 'VERSION))
(LOAD '((LISP) UMLMAC)))))
(DEFPROP GMT -4 TIMEZONE-OFFSET)
(DEFPROP EDT 0 TIMEZONE-OFFSET)
(DEFPROP EST 0 TIMEZONE-OFFSET)
(DEFPROP CDT 1 TIMEZONE-OFFSET)
(DEFPROP CST 1 TIMEZONE-OFFSET)
(DEFPROP MDT 2 TIMEZONE-OFFSET)
(DEFPROP MST 2 TIMEZONE-OFFSET)
(DEFPROP PDT 3 TIMEZONE-OFFSET)
(DEFPROP PST 3 TIMEZONE-OFFSET)
(DEFPROP MONDAY MONDAY DAY-VALUE)
(DEFPROP MON MONDAY DAY-VALUE)
(DEFPROP TUESDAY TUESDAY DAY-VALUE)
(DEFPROP TUESDAY TUE DAY-VALUE)
(DEFPROP WEDNESDAY WEDNESDAY DAY-VALUE)
(DEFPROP WEDNESDAY WED DAY-VALUE)
(DEFPROP THURSDAY THURSDAY DAY-VALUE)
(DEFPROP THURSDAY THU DAY-VALUE)
(DEFPROP FRIDAY FRIDAY DAY-VALUE)
(DEFPROP FRIDAY FRI DAY-VALUE)
(DEFPROP SATURDAY SATURDAY DAY-VALUE)
(DEFPROP SATURDAY SAT DAY-VALUE)
(DEFPROP SUNDAY SUNDAY DAY-VALUE)
(DEFPROP SUNDAY SUN DAY-VALUE)
(DEFPROP JANUARY 1 MONTH-VALUE)
(DEFPROP JAN 1 MONTH-VALUE)
(DEFPROP FEBRUARY 2 MONTH-VALUE)
(DEFPROP FEB 2 MONTH-VALUE)
(DEFPROP MARCH 3 MONTH-VALUE)
(DEFPROP MAR 3 MONTH-VALUE)
(DEFPROP APRIL 4 MONTH-VALUE)
(DEFPROP APR 4 MONTH-VALUE)
(DEFPROP MAY 5 MONTH-VALUE)
(DEFPROP JUNE 6 MONTH-VALUE)
(DEFPROP JUN 6 MONTH-VALUE)
(DEFPROP JULY 7 MONTH-VALUE)
(DEFPROP JUL 7 MONTH-VALUE)
(DEFPROP AUGUST 8 MONTH-VALUE)
(DEFPROP AUG 8 MONTH-VALUE)
(DEFPROP SEPTEMBER 9 MONTH-VALUE)
(DEFPROP SEP 9 MONTH-VALUE)
(DEFPROP SEPT 9 MONTH-VALUE)
(DEFPROP OCTOBER 10. MONTH-VALUE)
(DEFPROP OCT 10. MONTH-VALUE)
(DEFPROP NOVEMBER 11. MONTH-VALUE)
(DEFPROP NOV 11. MONTH-VALUE)
(DEFPROP DECEMBER 12. MONTH-VALUE)
(DEFPROP DEC 12. MONTH-VALUE)
(DEFUN TIME:PARSE-WORD-INTERNAL ()
(DECLARE (SPECIAL CHARS))
(DO ((L NIL (CONS C L))
(C (CAR CHARS) (CAR CHARS)))
((AND (OR (< C #/A) (> C #/Z))
(OR (< C #/a) (> C #/z)))
(IMPLODE (NREVERSE L)))
(SETQ C (IF (AND (NOT (< C #/a))
(NOT (> C #/z)))
(- C #.(- #/a #/A))
C))
(POP CHARS)))
(DEFUN TIME:PARSE-NUMBER-INTERNAL ()
(DECLARE (SPECIAL CHARS))
(DO ((FLAG NIL T)
(NUM 0 (+ (- (POP CHARS) #/0) (* NUM 10.))))
((NOT (MEMQ (CAR CHARS)
'(#/0 #/1 #/2 #/3 #/4 #/5 #/6 #/7 #/8 #/9)))
(AND FLAG NUM))))
(DEFUN GOTO MACRO (X)
#+DEBUG `(PROGN (FORMAT T "~&TO ~A N=~D. ~D//~D//~D ~D:~D:~D"
',(CADR X) N O D Y H M S)
(GO ,(CADR X)))
#-DEBUG `(GO ,(CADR X)))
(DEFUN TIME:PARSE-LIST (STRING)
(LET ((CHARS (EXPLODEN STRING))
/0 /1
(S -1) (M -1) (H -1)
(D -1) (O -1) (Y -1)
(Q 0.) (W NIL) (N -1) (X 0.) (R 0.))
(DECLARE (SPECIAL CHARS S M H D O Y))
(PROG ()
MAIN
(DO () ((OR (NULL CHARS)
(NOT (MEMBER (CAR CHARS)
'(#/( #/) #/- #\TAB #\SPACE #\LF #\CR)))))
(POP CHARS))
(IF (NULL CHARS) (GOTO RET))
(WHEN (= (CAR CHARS) #/,) ;Watch for MONTH DAY, YR
(POP CHARS)
(WHEN (NOT (MINUSP O))
(WHEN (NOT (MINUSP N))
(WHEN (MINUSP D)
(SETQ D N)
(SETQ N -1))))
(GOTO MAIN))
(LET ((NUM (TIME:PARSE-NUMBER-INTERNAL)))
(WHEN NUM
(IF (NOT (MINUSP N)) (GOTO SYN))
(SETQ N NUM)
(GOTO NUM)))
(SETQ /0 (TIME:PARSE-WORD-INTERNAL))
(WHEN (SETQ /1 (GET /0 'MONTH-VALUE))
(WHEN (NOT (MINUSP N))
(SETQ D N)
(SETQ N -1))
(SETQ X (LOGIOR X 2.))
(SETQ O /1)
(GOTO MAIN))
(WHEN (SETQ /1 (GET /0 'DAY-VALUE))
(SETQ W /1)
(GOTO MAIN))
(IF (EQ /0 'PM) (GOTO EVE))
(GOTO NOT-EVE)
EVE
(COND ((MINUSP H)
(IF (OR (MINUSP N) (PLUSP (- N 12.))) (GOTO SYN))
(SETQ H N)
(SETQ N -1.))
((NOT (MINUSP N)) (GOTO SYN)))
(IF (= H 12.) (SETQ H 0.))
(SETQ H (+ H 12.))
(GOTO MAIN)
NOT-EVE
(IF (EQ /0 'AM) (GOTO MORN))
(GOTO NOT-MORN)
MORN
(COND ((MINUSP H)
(IF (OR (MINUSP N) (PLUSP (- N 12.))) (GOTO SYN))
(SETQ H N)
(SETQ N -1.))
((NOT (MINUSP N)) (GOTO SYN)))
(IF (= H 12.) (SETQ H 0.))
(GOTO MAIN)
NOT-MORN
(IF (EQ /0 'THE) (GOTO MAIN))
(WHEN (SETQ /1 (GET /0 'TIMEZONE-OFFSET))
(SETQ Q (+ Q /1))
(GOTO MAIN))
(IF (MEMQ /0 '(AT IN ON)) (GOTO MAIN))
(IF (MEMQ /0 '(ST ND RD TH)) (GOTO DATE-END))
(WHEN (AND (EQ /0 'O)
(NOT (MINUSP N)))
(UNLESS (AND (= (POP CHARS) #/')
(EQ (TIME:PARSE-WORD-INTERNAL) 'CLOCK))
(GOTO SYN))
(SETQ H N)
(SETQ X (LOGIOR X 1.))
(SETQ N -1.)
(GOTO MAIN))
(IF (EQ /0 'A) (GOTO MAIN))
(WHEN (EQ /0 'NOON)
(IF (PLUSP (LOGAND X 1.)) (GOTO SYN))
(SETQ H 12.)
(SETQ M 0.)
(SETQ S 0.)
(SETQ X (LOGIOR X 1.))
(GOTO MAIN))
(WHEN (EQ /0 'NOW)
(SETQ X (LOGIOR X 1.))
(GOTO MAIN))
(WHEN (EQ /0 'TODAY)
(GOTO MAIN))
(WHEN (EQ /0 'TOMORROW)
(SETQ Q (+ Q 24.))
(GOTO MAIN))
(WHEN (EQ /0 'YESTERDAY)
(SETQ Q (- Q 24.))
(GOTO MAIN))
(WHEN (EQ /0 'HENCE)
(SETQ X (LOGIOR X 1.))
(SETQ /0 'AFTER))
(WHEN (MEMQ /0 '(AFTER FROM))
(IF (NOT (MINUSP N)) (GOTO SYN))
(SETQ Q (+ Q R))
(SETQ R 0.)
(GOTO MAIN))
(WHEN (MEMQ /0 '(AGO BEFORE))
(IF (NOT (MINUSP N)) (GOTO SYN))
(SETQ Q (- Q R))
(SETQ R 0.)
(GOTO MAIN))
(WHEN (EQ /0 'OF)
(IF (NOT (PLUSP R)) (GOTO MAIN))
(IF (NOT (ZEROP (\ R 24.))) (GOTO SYN))
(SETQ Q (+ Q (- R 24.)))
(SETQ R 0.)
(GOTO MAIN))
(WHEN (MEMQ /0 '(WK WKS WEEK WEEKS))
(SETQ R (+ R (* (IF (MINUSP N) 1 N) 168.)))
(SETQ N -1.)
(GOTO MAIN))
(WHEN (MEMQ /0 '(DY DYS DAY DAYS))
(SETQ R (+ R (* (IF (MINUSP N) 1 N) 24.)))
(SETQ N -1.)
(GOTO MAIN))
(WHEN (MEMQ /0 '(HR HRS HOUR HOURS))
(SETQ R (+ R (IF (MINUSP N) 1 N)))
(SETQ N -1.)
(GOTO MAIN))
(WHEN (MEMQ /0 '(AFTERNOON EVENING NIGHT LATE)) (GOTO EVE))
(WHEN (MEMQ /0 '(MORNING EARLY)) (GOTO MORN))
(WHEN (MINUSP N)
(PROG ()
(WHEN (MEMQ /0 '(FIFTY FIFTIETH )) (SETQ N 50.) (GOTO CK-UNITS))
(WHEN (MEMQ /0 '(FORTY FORTIETH )) (SETQ N 40.) (GOTO CK-UNITS))
(WHEN (MEMQ /0 '(THIRTY THIRTIETH)) (SETQ N 30.) (GOTO CK-UNITS))
(WHEN (MEMQ /0 '(TWENTY TWENTIETH)) (SETQ N 20.) (GOTO CK-UNITS))
(GOTO NOTENS)
CK-UNITS
(WHEN (= (CAR CHARS) #/-)
(POP CHARS)
(SETQ /0 (TIME:PARSE-WORD-INTERNAL))
(GOTO UNITS))
(RETURN T)
NOTENS
(WHEN (MEMQ /0 '(NINETEEN NINETEENTH )) (SETQ N 19.) (RETURN T))
(WHEN (MEMQ /0 '(EIGHTEEN EIGHTEENTH )) (SETQ N 18.) (RETURN T))
(WHEN (MEMQ /0 '(SEVENTEEN SEVENTEENTH)) (SETQ N 17.) (RETURN T))
(WHEN (MEMQ /0 '(SIXTEEN SIXTEENTH )) (SETQ N 16.) (RETURN T))
(WHEN (MEMQ /0 '(FIFTEEN FIFTEENTH )) (SETQ N 15.) (RETURN T))
(WHEN (MEMQ /0 '(FOURTEEN FOURTEENTH )) (SETQ N 14.) (RETURN T))
(WHEN (MEMQ /0 '(THIRTEEN THIRTEENTH )) (SETQ N 13.) (RETURN T))
(WHEN (MEMQ /0 '(TWELVE TWELFTH )) (SETQ N 12.) (RETURN T))
(WHEN (MEMQ /0 '(ELEVEN ELEVENTH )) (SETQ N 11.) (RETURN T))
(WHEN (MEMQ /0 '(TEN TENTH )) (SETQ N 10.) (RETURN T))
UNITS
(WHEN (MEMQ /0 '(NINE NINTH))
(IF (MINUSP N) (SETQ N 0.))
(SETQ N (+ N 9.))
(RETURN T))
(WHEN (MEMQ /0 '(EIGHT EIGHTH))
(IF (MINUSP N) (SETQ N 0.))
(SETQ N (+ N 8.))
(RETURN T))
(WHEN (MEMQ /0 '(SEVEN SEVENTH))
(IF (MINUSP N) (SETQ N 0.))
(SETQ N (+ N 7.))
(RETURN T))
(WHEN (MEMQ /0 '(SIX SIXTH))
(IF (MINUSP N) (SETQ N 0.))
(SETQ N (+ N 6.))
(RETURN T))
(WHEN (MEMQ /0 '(FIVE FIFTH))
(IF (MINUSP N) (SETQ N 0.))
(SETQ N (+ N 5.))
(RETURN T))
(WHEN (MEMQ /0 '(FOUR FOURTH))
(IF (MINUSP N) (SETQ N 0.))
(SETQ N (+ N 4.))
(RETURN T))
(WHEN (MEMQ /0 '(THREE THIRD))
(IF (MINUSP N) (SETQ N 0.))
(SETQ N (+ N 3.))
(RETURN T))
(WHEN (MEMQ /0 '(TWO SECOND))
(IF (MINUSP N) (SETQ N 0.))
(SETQ N (+ N 2.))
(RETURN T))
(WHEN (MEMQ /0 '(ONE FIRST A AN))
(IF (MINUSP N) (SETQ N 0.))
(SETQ N (+ N 1.))
(RETURN T))))
(IF (NOT (MINUSP N)) (GOTO NUM))
SYN
(ERROR "Syntax error in time spec" STRING)
DATE-END
(WHEN (AND (PLUSP N)
(MINUSP (- N 32.)))
(SETQ D N)
(SETQ N -1.)
(SETQ X (LOGIOR X 2.))
(GOTO MAIN))
(GOTO SYN)
NUM ;By now, N must have a positive number in it
(WHEN (AND (PLUSP (- N 1899.))
(MINUSP Y))
(SETQ Y (- N 1900.))
(SETQ N -1.)
(SETQ X (LOGIOR X 2.))
(GOTO MAIN))
(WHEN (< N 100.)
(COND ((= (CAR CHARS) #/:)
(IF (NOT (ZEROP (LOGAND X 1.))) (GOTO SYN))
(SETQ X (LOGIOR X 1.))
(IF (PLUSP (- N 24.)) (GOTO SYN))
(SETQ H N)
(SETQ N -1.)
(POP CHARS)
(SETQ M (TIME:PARSE-NUMBER-INTERNAL))
(IF (NOT M) (GOTO SYN))
(SETQ S (IF (NOT (= (CAR CHARS) #/:)) 0
(POP CHARS)
(TIME:PARSE-NUMBER-INTERNAL)))
(IF (NOT S) (GOTO SYN))
(GOTO SYN))
((MEMBER (CAR CHARS) '(#/- #//))
(IF (NOT (ZEROP (LOGAND X 2.))) (GOTO SYN))
(SETQ X (LOGIOR X 2.))
(POP CHARS)
(SETQ /0 (TIME:PARSE-NUMBER-INTERNAL))
(IF (NOT /0) (GOTO NOTDATE))
(IF (PLUSP (- N 12.)) (GOTO SYN))
(SETQ O N)
(SETQ N -1.)
(SETQ D /0)
(SETQ Y (IF (NOT (MEMBER (CAR CHARS) '(#// #/-))) 0
(TIME:PARSE-NUMBER-INTERNAL)))
(IF (NOT Y) (GOTO SYN))
(GOTO MAIN))))
NOTDATE
(WHEN (AND (NOT (MINUSP D))
(NOT (MINUSP O))
(MINUSP Y)
(> N 24.))
(SETQ Y N)
(SETQ X (LOGIOR X 2.))
(SETQ N -1.)
(GOTO MAIN))
(WHEN (AND (NOT (MINUSP Y))
(NOT (MINUSP O))
(NOT (MINUSP D)))
(WHEN (ZEROP (LOGAND X 1.))
(IF (< N 25.) (GOTO MAIN))
(SETQ H (// N 100.))
(SETQ M (- N (* H 100.)))
(SETQ S 0.)
(SETQ X (LOGIOR X 2.))
(SETQ N -1.)
(GOTO MAIN)))
(WHEN (AND (NOT (MINUSP O))
(MINUSP D)
(OR (ZEROP (LOGAND X 1.))
(AND (NOT (MINUSP H))
(NOT (MINUSP M))
(NOT (MINUSP S)))))
(SETQ D N)
(SETQ X (LOGIOR X 2.))
(SETQ N -1.)
(GOTO MAIN))
(GOTO MAIN)
RET
(WHEN (NOT (MINUSP N))
(WHEN (MINUSP D)
(SETQ D N) (SETQ N -1.) (SETQ X (LOGIOR X 2.)) (GOTO DEFAULTS))
(WHEN (MINUSP Y)
(WHEN (> N 24.)
(SETQ Y N) (SETQ N -1.) (SETQ X (LOGIOR X 2.)) (GOTO DEFAULTS)))
(WHEN (MINUSP H)
(SETQ H N) (SETQ N -1.) (SETQ X (LOGIOR X 1.)) (GOTO DEFAULTS))
(GOTO SYN))
DEFAULTS
(LET ((DATE (STATUS DATE))
(DOW (STATUS DOW))
(TIME (STATUS DAYTIME)))
(WHEN (NOT (EQUAL (STATUS DATE) DATE)) ;just after midnite?
(SETQ DATE (STATUS DATE))
(SETQ DOW (STATUS DOW))
(SETQ TIME (STATUS DAYTIME)))
(PROG ()
(WHEN (AND (NOT (ZEROP (LOGAND X 1.)))
(MINUSP H)
(MINUSP M)
(MINUSP S))
(SETQ H (CAR TIME) M (CADR TIME) S (CADDR TIME)))
(IF (MINUSP H) (SETQ H 0.))
(IF (MINUSP M) (SETQ M 0.))
(IF (MINUSP S) (SETQ S 0.))
(WHEN (AND (NOT (ZEROP (LOGAND X 2.)))
(MINUSP Y)
(MINUSP O)
(MINUSP D))
(GOTO TODAY))
(IF (NOT (ZEROP (LOGAND X 2.))) (GOTO NOT-TODAY))
TODAY
(SETQ Y (CAR DATE))
(SETQ O (CADR DATE))
(SETQ D (CADDR DATE))
NOT-TODAY
(IF (MINUSP Y) (SETQ Y (CAR DATE)))
(IF (MINUSP O) (SETQ O (IF (MINUSP D) 1 (CADR DATE))))
(IF (MINUSP D) (SETQ D 1.)))
(WHEN (NOT (ZEROP Q))
(SETQ /0 (+ 1 (* 2 (IF (PLUSP Q) -1 0))))
(SETQ H (+ H Q))
(PROG ()
TOP
(TIME:NORMALIZE-DATE-INTERNAL)
(IF (AND (NOT (MINUSP H)) (< H 24.))
(RETURN T))
(SETQ W NIL)
(SETQ H (+ H (* 24. /0)))
(SETQ D (- D /0))
(GO TOP)))
;W holds specified date or NIL. We ignore that for now...
(RETURN
(LIST S M H D O Y
(TIME:DAY-OF-THE-WEEK-STRING
(TIME:ON-WHAT-DAY-OF-THE-WEEK? D O Y))))))))
(DEFUN TIME:NORMALIZE-DATE-INTERNAL ()
(DECLARE (SPECIAL Y O D H M S))
(PROG (TT X)
(IF (AND (PLUSP D) (MINUSP (- D 29.))) (RETURN T))
(SETQ TT (TIME:ON-WHAT-DAY-OF-THE-WEEK? D O Y))
(COND ((NOT (PLUSP D))
(SETQ O (1- O))
(SETQ D 28.)
(WHEN (ZEROP O) (SETQ O 12.) (SETQ Y (1- Y)))
(SETQ X (TIME:ON-WHAT-DAY-OF-THE-WEEK? D O Y))
(IF (MINUSP (- TT X)) (SETQ TT (+ TT 7)))
(SETQ D (+ D TT (- X))))
(T
(LET ((YY Y) (OO (1+ O)) (DD 1))
(WHEN (> O 12.) (SETQ O 1) (SETQ Y (1+ Y)))
(SETQ X (TIME:ON-WHAT-DAY-OF-THE-WEEK? DD OO YY))
(IF (ZEROP (- X TT)) (SETQ Y YY O OO D DD)))))))