计算时间的差与和

#lang racket

(require racket/date)


(define display-date-with-chinese
  (lambda (seconds)
    (displayln (date->string (seconds->date seconds)
                             (date-display-format 'chinese)))))

(define get-seconds
  (lambda (date)
    (match date
      [(list year month day '- hour minute second)
       (find-seconds second
                     minute
                     hour
                     day
                     month
                     year
                     #t)])))

(define add-and-display-date
  (lambda (seconds time)
    (display-date-with-chinese (+ seconds
                                  (* (car time) 3600)
                                  (* (cadr time) 60)
                                  (caddr time)))))

(define date-add
  (case-lambda
    [(time) (add-and-display-date (current-seconds) time)]
    [(date time)
     (add-and-display-date (get-seconds date) time)]))

;; 计算当前时刻加上 2 个小时,30 分钟,15 秒之后的时间
(date-add '(2 30 15))
;; => "2015/4/11 星期六 20:24:19"

;; 计算 2015 年 4 月 11 号 17 点 50 分 21 秒加上 1000 分钟后的时间
(date-add '(2015 4 11 - 17 50 21) '(0 1000 0))
;; => "2015/4/12 星期天 10:30:21"


;; 例如求解 (hex-calc 54321 '(60 60))
;; 解为 '(21 5 15)
;; 问题与解的对应关系为 21 + 5*60 + 15*(60*60) = 54321
(define hex-calc
  (lambda (number hex-list)
    (cond [(empty? hex-list) (list number)]
          [else
           (let ([current-hex (car hex-list)])
             (cons (remainder number current-hex)
                   (hex-calc (quotient number current-hex)
                             (cdr hex-list))))])))

(define display-time
  (lambda (seconds1 seconds2)
    (let ([format-time (hex-calc (abs (- seconds1
                                         seconds2))
                                 '(60 60))])
      (printf "相差 ~a 小时 ~a 分钟 ~a 秒\n"
              (third format-time)
              (second format-time)
              (first format-time)))))

(define date-sub
  (case-lambda
    [(date) (display-time (current-seconds) (get-seconds date))]
    [(date1 date2) (display-time (get-seconds date1)
                                 (get-seconds date2))]))

;; 计算 2011 年 4 月 11 号 17 点 50 分 21 秒与当前时间的时间差
(date-sub '(2011 4 11 - 17 50 21))
;; => 相差 35069 小时 46 分钟 13 秒

;; 计算 2011 年 4 月 11 号 17 点 50 分 21 秒与
;; 2015 年 4 月 11 号 17 点 50 分 00 秒的时间差
(date-sub '(2011 4 11 - 17 50 21) '(2015 4 11 - 17 50 00))
;; => 相差 35063 小时 59 分钟 39 秒