[local-time-devel] Adding java Calendar 'like' math to local-time

Andrea Chiumenti kiuma72 at gmail.com
Tue Mar 25 13:16:28 UTC 2008


Hello ppl,

I've added the following functionality to local time,
I only wonder if it's not the case to render the internal *-add-*
functions as methods.

Have a nice day,
kiuma


(defgeneric local-time-add (local-time field value)
  (:documentation "Adds the specified amount of VALUE to the LOCAL_TIME.
FIELD may be any of:
* 'NSEC nano-seconds
* 'MSEC milli-seconds
* 'SEC seconds
* 'MIN minutes
* 'HR hours
* 'DAY days
* 'MONTH monthes
* 'YEARS years.
And other FIELD value will produce an error condition."))

(defun local-time-add-year (local-time value)
  (multiple-value-bind (ns ss mm hh day month year)
      (decode-local-time local-time)
    (encode-local-time ns ss mm hh day month (+ year value))))

(defun local-time-add-month (local-time value)
  (multiple-value-bind (d-month d-year)
      (floor (abs value) 12)
    (when (< value 0)
      (setf d-month (- d-month)
            d-year (- d-year))
      (multiple-value-bind (ns ss mm hh day month year)
          (decode-local-time local-time)
        (multiple-value-bind (ns ss mm hh day month-ignore year)
            (decode-local-time (encode-local-time ns ss mm hh day 1 (+
year d-year)))
            (encode-local-time ns ss mm hh day month year))))))

(defun local-time-add-day (local-time value)
  (let* ((curr-day (day-of local-time))
         (local-time-result (make-instance 'local-time
                                          :day curr-day
                                          :sec (sec-of local-time)
                                          :nsec (nsec-of local-time)
                                          :time-zone (timezone-of local-time))))
    (setf (day-of local-time-result) (+ curr-day value))
    local-time-result))

(defun local-time-add-hour (local-time value)
  (multiple-value-bind (ns ss mm hh day month year)
          (decode-local-time local-time)
    (multiple-value-bind (d-hour d-day)
        (floor (abs value) 24)
      (when (< value 0)
        (setf d-hour (- d-hour)
              d-day (- d-day)))
      (let ((local-time-result (local-time-add-day local-time d-day)))
        (multiple-value-bind (ns2 ss2 mm2 hh2 day2 month2 year2)
            (decode-local-time local-time-result)
          (encode-local-time ns2 ss2 mm2 (+ hh d-hour) day2 month2 year2))))))

(defun local-time-add-min (local-time value)
  (multiple-value-bind (ns ss mm hh day month year)
          (decode-local-time local-time)
    (multiple-value-bind (d-min d-hour)
        (floor (abs value) 60)
      (when (< value 0)
        (setf d-min (- d-min)
              d-hour (- d-hour)))
      (let ((local-time-result (local-time-add-hour local-time d-hour)))
        (multiple-value-bind (ns2 ss2 mm2 hh2 day2 month2 year2)
            (decode-local-time local-time-result)
          (encode-local-time ns2 ss2 (+ mm d-min) hh2 day2 month2 year2))))))

(defun local-time-add-sec (local-time value)
  (multiple-value-bind (ns ss mm hh day month year)
          (decode-local-time local-time)
    (multiple-value-bind (d-sec d-min)
        (floor (abs value) 60)
      (when (< value 0)
        (setf d-sec (- d-sec)
              d-min (- d-min)))
      (let ((local-time-result (local-time-add-min local-time d-min)))
        (multiple-value-bind (ns2 ss2 mm2 hh2 day2 month2 year2)
            (decode-local-time local-time-result)
          (encode-local-time ns2 (+ ss d-sec) mm2 hh2 day2 month2 year2))))))

(defun local-time-add-nsec (local-time value)
  (multiple-value-bind (ns ss mm hh day month year)
          (decode-local-time local-time)
    (multiple-value-bind (d-nsec d-sec)
        (floor (abs value) 10000000)
      (when (< value 0)
        (setf d-nsec (- d-nsec)
              d-sec (- d-sec)))
      (let ((local-time-result (local-time-add-sec local-time d-sec)))
        (multiple-value-bind (ns2 ss2 mm2 hh2 day2 month2 year2)
            (decode-local-time local-time-result)
          (encode-local-time (+ ns d-nsec) ss2 mm2 hh2 day2 month2 year2))))))


;;; make this extern <<-----------------------------
(defmethod local-time-add ((local-time local-time) field value)
  (ccase field
    (NSEC (local-time-add-nsec local-time value))
    (SEC (local-time-add-sec local-time value))
    (MIN (local-time-add-min local-time value))
    (HR (local-time-add-hour local-time value))
    (DAY (local-time-add-day local-time value))
    (MONTH (local-time-add-month local-time value))
    (YEAR (local-time-add-year local-time value))))



More information about the local-time-devel mailing list