use*_*324 1 lisp common-lisp date-arithmetic
我试图使用给定的出生日期(表格的一串YYYY-MM-DD)计算一个人在Common Lisp中的年龄但我得到以下错误:
错误:
"2013-12-10"' is not of the expected type数字'
我的代码如下
(defun current-date-string ()
"Returns current date as a string."
(multiple-value-bind (sec min hr day mon yr dow dst-p tz)
(get-decoded-time)
(declare (ignore sec min hr dow dst-p tz))
(format nil "~A-~A-~A" yr mon day)))
(defvar (dob 1944-01-01))
(let ((age (- (current-date-string) dob))))
Run Code Online (Sandbox Code Playgroud)
谁可以在这方面给我帮助?我怀疑当前日期是字符串格式,如我的输入,但我们如何将其转换为与我的输入相同的日期格式?
有两个直接的问题:
-将数字作为参数.你传递的结果(current-date-string),这是一个字符串所生产(format nil "~A-~A-~A" yr mon day).这段代码没有任何意义:
(defvar (dob 1944-01-01))
(let ((age (- (current-date-string) dob))))
Run Code Online (Sandbox Code Playgroud)
一方面它没有正确缩进.它有两种形式,第一种形式(defvar (dob 1944-01-01)).这不是正确的语法defvar. 1944-01-01是一个符号,它没有绑定,所以即使你已经完成了(defvar dob 1944-01-01),你在评估定义时也会遇到错误.虽然(let ((age (- (current-date-string) dob))))在语法上是正确的,但是在绑定年龄后你没有做任何事情.你可能想要这样的东西(let ((age (- (current-date-string) dob))) <do-something-here>).
无论如何,通用时间是以秒为单位的整数值:
25.1.4.2世界时
世界时是一个绝对时间,表示为单个非负整数---自1900年1月1日午夜(忽略闰秒)以来的秒数.因此,时间1是格林威治标准时间1900年1月1日00:00:01(即上午12:00:01).
这意味着您可以采用两个通用时间并从另一个中减去一个以获得持续时间(以秒为单位).遗憾的是,Common Lisp不提供操作这些持续时间的功能,并且由于闰年等原因而转换它们并非易事.Common Lisp Cookbook提到了这一点:
日期和时间
由于世界时代只是数字,因此它们比日历时间更容易操作更安全.如果可能的话,日期和时间应始终存储为通用时间,并且仅出于输出目的而转换为字符串表示.例如,通过简单地将两个相应的通用时间与<相比较,可以直接知道两个日期中的哪一个出现在另一个之前.另一个典型问题是如何计算两个给定日期之间的"时间距离".让我们看看如何用一个例子来做到这一点:具体来说,我们将计算第一次登陆月球(美国东部时间下午4:17,1969年7月20日)和最后一次起飞挑战者(美国东部时间上午11:38)之间的时间距离. ,1986年1月28日).
Run Code Online (Sandbox Code Playgroud)* (setq *moon* (encode-universal-time 0 17 16 20 7 1969 4)) 2194805820 * (setq *takeoff* (encode-universal-time 0 38 11 28 1 1986 5)) 2716303080 * (- *takeoff* *moon*) 521497260这有点超过5200万秒,相当于6035天,20小时和21分钟(您可以通过将该数字连续除以60,60和24来验证这一点).超越几天是有点困难,因为几个月和几年没有固定的长度,但上述约为16年半.
听起来你还需要从表单的字符串中读取日期YYYY-MM-DD.如果您确信您所获得的价值是合法的,那么您可以做一些简单的事情
(defun parse-date-string (date)
"Read a date string of the form \"YYYY-MM-DD\" and return the
corresponding universal time."
(let ((year (parse-integer date :start 0 :end 4))
(month (parse-integer date :start 5 :end 7))
(date (parse-integer date :start 8 :end 10)))
(encode-universal-time 0 0 0 date month year)))
Run Code Online (Sandbox Code Playgroud)
这将返回一个通用时间,您可以按上述方法进行算术运算.
作为一个懒惰的程序员,这通常是一种很好的做法.在这种情况下,我们可能会因为不自己实现这些类型的函数而变得懒惰,而是使用一个可以为我们处理它的库.一些Common Lisp实现可能已经提供了日期和时间函数,并且Cliki上列出了许多时间库.我不知道哪些是最广泛使用的,或者覆盖了你需要的各种函数,而且库建议对于StackOverflow来说是偏离主题的,所以你可能需要尝试一些来找到一个适用于它的函数您.