nm03's phlog talked about using date python packages. I thought I would try something like that with common lisp. If you install ecl and download 0time-adder.lisp and 0make-your-time.lisp from my 1common-lisp, it should run happily pretty much everywhere. ecl --load make-your-time.lisp will build time-adder.lisp into a-b+c.exe, which has some notion of help text (-h or --help). I had forgotten that dates are really hard to work with (is it a leap year? When is the next leap year? How many days in this month?). I resolved these in a way I think you see sometimes, where you specify your time delta as being between two dates with every field defaulting to the current date, and the delta of those first two time/dates getting added to a third date (default: the day and timezone your computer thinks it is). When I try the experiment my help text proposes it does this: $ ecl --load make-your-time.lisp .. $ ./a-b+c.exe <<EOG > ((minute . 6) (hour . 3)) > ((minute . 14) (hour . 1)) > ((date . 3) (year . 1992)) > EOG ((SECOND . 9) (MINUTE . 36) (HOUR . 1) (DATE . 4) (MONTH . 5) (YEAR . 1992) (TIMEZONE . 6)) Writing dotted association lists like that is a lisp idiom. I'm also catting the text of time-adder.lisp here: (defpackage time-adder (:use cl)) (in-package time-adder) (defun alist2seconds (alist) (multiple-value-bind (second minute hour date month year day summerp timezone) (get-decoded-time) (declare (ignore day summerp)) (apply 'encode-universal-time (mapcar (lambda (name default) (or (cdr (assoc name alist)) default)) '(second minute hour date month year timezone) (list second minute hour date month year timezone))))) (defun seconds2alist (seconds) (multiple-value-bind (second minute hour date month year day summerp timezone) (decode-universal-time seconds) (declare (ignore day summerp)) (mapcar 'cons '(second minute hour date month year timezone) (list second minute hour date month year timezone)))) (defun a-b+c (&optional (a nil) (b nil) (c nil) &aux (a (when (listen) (read nil nil))) (b (when (listen) (read nil nil))) (c (when (listen) (read nil nil)))) (seconds2alist (+ (- (alist2seconds a) (alist2seconds b)) (alist2seconds c)))) (defun help-text () (print "Try running ./a-b+c.exe with no standard inputs. Its defaults for a, b and c are the current time. Then maybe try ./a-b+c.exe <<EOG ((minute . 6) (hour . 3)) ((minute . 14) (hour . 1)) EOG or ./a-b+c.exe <<EOG ((minute . 6) (hour . 3)) ((minute . 14) (hour . 1)) ((date . 3) (year . 1992)) EOG ")) (when (or (string= "--help" (second (ext:command-args))) (string= "-h" (second (ext:command-args)))) (help-text)) (handler-case (loop (prin1 (a-b+c)) (terpri) (let ((char (read-char-no-hang t nil))) (if char (unread-char char) (return)))) (t (error) (format t "Error: ~a~%" error) (help-text))) (si:quit)