;;; ;;; $Id: date.el,v 1.1 1998/03/21 15:13:13 mcmanr Exp mcmanr $ ;;; ;;; a library of date functions. the purpose of the library ;;; is to make it convenient to do date arithmetic. to that ;;; end, the conept of day count is established. a day count ;;; is a positive integer representing a number of days from ;;; some base date in the past. ;;; ;;; since this library's original use was for financial ;;; calculations, by default the date range supported is between ;;; 1900 and 2200. these numbers are defvar'ed and can be ;;; changed easily. ;;;

(defvar date-start-year 1900 "Minimum year handled. Also, this is the base year for day counts. January 1 of this year is defined to be day count 0.")

(defvar date-end-year 2200 "Maximum year handled.")

(defvar date-year-vect (let ((vect (make-vector (- date-end-year date-start-year) nil)) (tot 0) (year date-start-year)) (while (< year date-end-year) (setf (aref vect (- year date-start-year)) tot) (incf tot (date-day-count-in-year year)) (incf year)) vect) "A vector in which each cell represents the day count for January 1 of a particular year. the formula to get from a year to an index in this vector is: (- year date-start-year)")

(defvar date-day-count-in-month-vect [0 31 28 31 30 31 30 31 31 30 31 30 31] "A vector where each cell represents the number of days in a particular month. Obviously, additional calculation is required to handle February. The array is indexed with January in position 1.")

(defun date-day-count-to-mdy (day-count) "Given a DAY-COUNT return a list of three elements that specify that corresponding month, day, and year. Month indices start with 1, corresponding to January. Day indices start with 1, corresponding to the first day of the month." (date-valid-day-count day-count) (flet ((guess-year-index () (let ((n (max (1- (/ day-count 365)) 0))) n)) (year-index-to-year (index) (+ index date-start-year))) (let* ((nyear (- date-end-year date-start-year)) (year-index (guess-year-index)) (before-day-count)) ;; search for the correct year by choosing a good guess year, ;; and then searching forward until you go past the desired ;; year. the desired year is then previous year. (while (progn (setf before-day-count (aref date-year-vect year-index)) (<= before-day-count day-count)) (incf year-index)) (setf year-index (max 0 (1- year-index))) ;; now find the right month in the year. a similar approach ;; is used. add up the days in each month until the total day ;; count is greater than the given day count. at this point, ;; you've gone too far by one month, so back off the last month. (let ((year (year-index-to-year year-index)) (guess-day-count (aref date-year-vect year-index)) (month 1) (day 1) (dim nil)) (while (progn (setf dim (date-day-count-in-month month year)) (incf guess-day-count dim) (<= guess-day-count day-count)) (incf month)) (incf guess-day-count (* -1 dim)) ;; now figure the number of days into the month (let ((day (1+ (- day-count guess-day-count)))) (list month day year))))))

(defun date-mdy-to-day-count (month day year) "Given a MONTH, a DAY, and a YEAR, return a corresponding day count. The day count is defined to be 0 on January 1 of 'date-start-year', and it is incremented by one each day after that. The MONTH spec should be between 1 and 12, the DAY spec should be between 1 and 31, depending on the month, and the year must be between 'date-start-year' and 'date-end-year'." (date-valid-mdy month day year) (flet ((day-count-to-start-of-month (month year) (let ((start-month 1) (count 0)) (while (< start-month month) (incf count (date-day-count-in-month start-month year)) (incf start-month)) count))) (+ (1- day) (day-count-to-start-of-month month year) (aref date-year-vect (- year date-start-year)))))

(defun date-tester (max-day-count) "Insert at the end of the current buffer a bunch of lines that test the functionality of this date library. MAX-DAY-COUNT is the final day count to test; the testing begins at a day count of 0. The left most column represents the day count being tested. The next three columns are the month, day, and year corresponding to the day count in the first column. The fifth column is the day count returned by converting the month, day, and year back into a day count. It's value should match the first column." (interactive "p") (let ((day-count 0) (mdy nil)) (goto-char (point-max)) (while (< day-count max-day-count) (let ((mdy (date-day-count-to-mdy day-count))) (insert (format "%6d " day-count) (format "%2d %2d %4d " (nth 0 mdy) (nth 1 mdy) (nth 2 mdy)) (format "%6d\n" (apply 'date-mdy-to-day-count mdy))) (incf day-count)))))

(provide 'date)

Tue, 12 Sep 2000 03:00:00 GMT

David B. Lamkin#3 / 3

Date routines for CL?

Take a look in ftp://ftp.cs.umass.edu/pub/eksl/utils/ . The last time I took a look here, utils-5.tgz was the latest, and contains a file day-and-time.lisp that has what you seek. I think that the other files are different versions, but I'm not sure why they would have such widely differing sizes; perhaps some include binaries.

Quote:

> I'm just wondering if there is a DATE package floating around anywhere > that handles:

> o Parsing of dates > o Formatting of dates > o Date math

> I appreciate that CL has the universal time functions, which would be > a fine foundation to build upon, but I'm just looking for something a > little more high level before jaunting off to code my own.

> I checked the some of the Lisp archives, and I also checked SLIB > (thinking I could port it rather easily), but it, surprisingly, > doesn't have anything either.