(define-condition time-string-parse-error (parse-error)
())
(define-condition invalid-time-string-error (time-string-parse-error)
((string :initarg :string))
(:report (lambda (condition stream)
(format stream "Invalid time string: ~S"
(slot-value condition 'string)))))
(defun parse-time-string (string)
(unless (stringp string)
(error 'type-error :datum string :expected-type 'string))
(unless (every (lambda (c)
(find c (concatenate 'string "012345679: " #(#\Tab))))
string)
(error (make-condition 'invalid-time-string-error :string string)))
(unless (= (count #\: string) 2)
(error (make-condition 'invalid-time-string-error :string string)))
(let* ((c1 (position #\: string))
(c2 (position #\: string :start (1+ c1)))
(parts (list (subseq string 0 c1)
(subseq string (1+ c1) c2)
(subseq string (1+ c2))))
(parts (mapcar (lambda (x)
(handler-case (parse-integer x :radix 10)
(parse-error (e) e)))
parts)))
(unless (and (= (length parts) 3)
(every #'integerp parts))
(error (make-condition 'invalid-time-string-error :string string)))
(destructuring-bind (h m s) parts
(unless (and (<= 0 h 23)
(<= 0 m 59)
(<= 0 s 59))
(error (make-condition 'invalid-time-string-error :string string))))
parts))
(defun +sec (time-string sec)
(destructuring-bind (h m s)
(parse-time-string time-string)
(let ((time (+ (* h 60 60)
(* m 60)
(* s 1)
sec)))
(multiple-value-setq (time s) (floor time 60))
(multiple-value-setq (time m) (floor time 60))
(multiple-value-setq (time h) (floor time 24))
(format nil "~2,'0D:~2,'0D:~2,'0D" h m s))))
(loop for s = (read-line nil nil)
while s
for a = (handler-case (+sec s 1)
(invalid-time-string-error (e)
(princ-to-string e)))
do (write-line a))