轨道
/
Common Lisp
Common Lisp
/
练习
/
十亿秒纪念日
十亿秒纪念日

十亿秒纪念日

学习练习

简介

日期与时间

在 Common Lisp 中,时间有四种表示方式,这里只会涉及其中两种。

  • 通用时间是一个绝对时间,它是一个整数,表示自1900-01-01T00:00:00Z以来的秒数(也就是 1900 年 1 月 1 日 UTC 时间的午夜)。
  • 解码时间是一个由 9 个值组成的元组,它们合在一起表示一个具体的日历时间:秒、分、时、日、月、年、星期、夏令时标志、时区。 (下面会详细讨论。)

通用时间

要获取当前的通用时间,可以使用get-universal-time或get-decoded-time。 前者返回自1900-01-01T00:00Z以来的当前秒数,后者以解码格式返回同样的数据。

解码时间

decode-universal-time和encode-universal-time是处理时间的主要函数。 前者接受一个通用时间,并以多值的形式返回一个解码时间值;后者接受各个解码时间值作为实参,返回一个通用时间。

两者都接受一个可选的时区实参。 时区的格式见下文。

解码时间是一组值:

  • 秒:0 到 59 之间的整数
  • 分:0 到 59 之间的整数
  • 时:0 到 23 之间的整数
  • 日:1 到 31 之间的整数(上限显然取决于月份和年份)
  • 月:1 到 12 之间的整数
  • 年:表示年份的整数。
  • 星期:0 到 6 之间的整数。0 表示星期一,1 表示星期二,依此类推,6 表示星期日。
  • 夏令时标志:值为 true 时表示夏令时正在生效。
  • 时区:一个介于 -24 和 24 之间的小时数,表示与 UTC 的偏移量。 该数是一个有理数,并且必须是1/3600的整数倍
(encode-universal-time 1 2 3 4 5 2000 0) ; => 3166398121
(decode-universal-time 3166398121)       ; => 1
                                         ;    2
                                         ;    3
                                         ;    4
                                         ;    5
                                         ;    2000
                                         ;    3 (Thursday)
                                         ;    NIL
                                         ;    0
(decode-universal-time 2208988800) ; => 0
                                   ;    0
                                   ;    0
                                   ;    1
                                   ;    1
                                   ;    1970
                                   ;    3
                                   ;    NIL
                                   ;    0

多值

在 Common Lisp 中,函数不仅能返回一个值,还能返回多个值。 例如floor会向零的方向取整,它返回两个值,第一个是取整后的值,第二个是余数。

(floor 3.5) ; => 3
            ;    0.5

(下面我们会把返回的多个值分行展示。)

返回多个值

如果你想让一个函数返回多个值,可以使用values访问器:

(defun three-numbers () (values 1 2 3))
(three-numbers) ; => 1
                ;    2
                ;    3

处理多个值

如果你只关心第一个值,那就不需要做任何特殊处理,语言会自动帮你处理好:

(+ (values 1 2 3) (values 10 20 30)) ; => 11

不过,如果你想访问其他那些值,就需要用到几个函数。 两个主要的宏是multiple-value-list和multiple-value-bind。 它们用来包裹返回多个值的表达式,并捕获所有的值。 第一个会创建一个包含所有值的列表。 第二个让你把变量绑定到各个值上。

(multiple-value-list (values 1 2 3))                   ; => (1 2 3)
(multiple-value-bind (a b c) (values 1 2 3) 
   (+ a b c)) ; => 6

另一个有用的函数是nth-value

说明

Lisp Aliens 喜欢庆祝周年纪念日。 在他们看来,重要的周年纪念日是十亿秒。 也就是:从事件发生起经过 1,000,000,000 秒。

1. 计算十亿秒纪念日

写一个函数from,它接受 6 个参数:year、month、day、hour、min、sec,并计算十亿秒纪念日的日期和时间。 这个函数应以数组的形式返回日期,顺序和含义与输入的参数一致。

(from 2000 1 1 0 0 0) ; => (2031 9 9 1 46 40)
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Common Lisp Exercism

准备好开始 十亿秒纪念日 了吗?

注册 Exercism,借助 27 个概念92 个练习 和真人导师指导,学习并掌握 Common Lisp,全部免费。