You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:33:15