Chez Scheme处理1970年前公历日期的技术求助
在Chez Scheme中处理1970年1月1日之前的日期
Chez Scheme内置的make-date依赖Unix时间戳(以1970-01-01为纪元起点),因此无法直接创建该日期之前的date对象。以下是两种可行的解决思路:
1. 手动实现公历日期处理逻辑
自己编写日期合法性校验、年龄计算等核心逻辑,无需依赖系统内置的日期结构:
;; 定义日期结构体,包含基础合法性校验 (define-record-type date (fields year month day) (protocol (lambda (new) (lambda (year month day) (if (and (integer? year) (integer? month) (integer? day) (<= 1 month 12) (<= 1 day (case month ((4 6 9 11) 30) ((2) (if (or (zero? (mod year 400)) (and (zero? (mod year 4)) (not (zero? (mod year 100))))) 29 28)) (else 31)))) (new year month day) (error "invalid date")))))) ;; 计算出生日期到当前日期的年龄 (define (calculate-age birth-date current-date) (let ((by (date-year birth-date)) (bm (date-month birth-date)) (bd (date-day birth-date)) (cy (date-year current-date)) (cm (date-month current-date)) (cd (date-day current-date))) (let ((base (- cy by))) (if (or (< bm cm) (and (= bm cm) (<= bd cd))) base (- base 1))))) ;; 测试示例 (define birth (make-date 1955 5 1)) (define today (make-date 2024 10 15)) (calculate-age birth today) ; 输出69
2. 转换为负时间戳适配内置函数
通过计算目标日期与1970-01-01的天数差,生成负时间戳后,用time-utc->date解析:
;; 计算从公元1年1月1日到目标日期的总天数(简化实现,可扩展完善闰年规则) (define (date-to-day-count year month day) (let loop ((y 1) (total 0)) (if (= y year) (+ total (apply + (map (lambda (m) (case m ((4 6 9 11) 30) ((2) (if (or (zero? (mod y 400)) (and (zero? (mod y 4)) (not (zero? (mod y 100))))) 29 28)) (else 31))) (iota (- month 1))))) (loop (+ y 1) (+ total (if (or (zero? (mod y 400)) (and (zero? (mod y 4)) (not (zero? (mod y 100))))) 366 365)))))) ;; 1970-01-01对应的总天数 (define epoch-day (date-to-day-count 1970 1 1)) ;; 将日期转换为UTC时间戳(秒) (define (date-to-timestamp year month day) (* (- (date-to-day-count year month day) epoch-day) 86400)) ;; 生成1955年5月1日的date对象 (time-utc->date (date-to-timestamp 1955 5 1) #f)
内容的提问来源于stack exchange,提问作者Sem-Joe
相关产品推荐
相关产品推荐

