-(export 'timespec-seconds)
-(defun timespec-seconds (ts)
- "Convert a timespec TS to seconds.
-
- A timespec may be a real count of seconds, or a list (COUNT UNIT). UNIT
- may be any of a number of obvious time units."
- (cond ((null ts) 0)
- ((realp ts) (floor ts))
- ((atom ts)
- (error "Unknown timespec format ~A" ts))
- ((null (cdr ts))
- (timespec-seconds (car ts)))
- (t (+ (to-integer (* (car ts)
- (case (intern (string-upcase
- (stringify (cadr ts)))
- '#:zone)
- ((s sec secs second seconds) 1)
- ((m min mins minute minutes) 60)
- ((h hr hrs hour hours) #.(* 60 60))
- ((d dy dys day days) #.(* 24 60 60))
- ((w wk wks week weeks) #.(* 7 24 60 60))
- ((y yr yrs year years) #.(* 365 24 60 60))
- (t (error "Unknown time unit ~A"
- (cadr ts))))))
- (timespec-seconds (cddr ts))))))
+(let ((unit-scale (make-hash-table)))
+
+ (dolist (item `(((:second :seconds :sec :secs :s) ,1)
+ ((:minute :minutes :min :mins :m) ,60)
+ ((:hour :hours :hr :hrs :h) ,(* 60 60))
+ ((:day :days :dy :dys :d) ,(* 24 60 60))
+ ((:week :weeks :wk :wks :w) ,(* 7 24 60 60))))
+ (destructuring-bind (units scale) item
+ (dolist (unit units) (setf (gethash unit unit-scale) scale))))
+
+ (export 'timespec-seconds)
+ (defun timespec-seconds (ts)
+ "Convert a timespec TS to seconds.
+
+ A timespec may be a real count of seconds, or a list ({COUNT UNIT}*).
+ UNIT may be any of a number of obvious time units."
+ (labels ((convert (acc ts)
+ (cond ((null ts) acc)
+ ((realp ts) (+ acc (floor ts)))
+ ((atom ts) (error "Unknown timespec format ~A" ts))
+ (t
+ (destructuring-bind
+ (count &optional unit &rest tail) ts
+ (let ((scale
+ (acond ((null unit) 1)
+ ((gethash (intern (string-upcase
+ (stringify unit))
+ :keyword)
+ unit-scale)
+ it)
+ (t
+ (error "Unknown time unit ~S"
+ unit)))))
+ (convert (+ acc (to-integer (* count scale)))
+ tail)))))))
+ (convert 0 ts))))