Skip to content

Lisp - 日期与时间

在软件开发中,处理日期和时间是一个常见的需求。Common Lisp 提供了一个低层级、可移植的时间标准,称为 Universal Time(通用时间)。对于更复杂和更方便开发者的操作,现代生态系统依赖于外部库。本教程将涵盖这两种方法。

Common Lisp 的内置时间函数围绕 Universal Time 展开,它是一个整数,表示自格林威治标准时间(GMT)1900年1月1日午夜以来经过的秒数。

  • get-universal-time:以整数形式返回当前的 Universal Time。这是获取时间戳(timestamp)的主要方式。
  • decode-universal-time:将 Universal Time 整数转换为九个值,以便于检查:秒、分、时、日、月、年、星期几(周一=0)、夏令时标志和与 GMT 的时区偏移。
  • encode-universal-time:执行反向操作,将九个解码值转换回 Universal Time 整数。
  • get-decoded-time: (decode-universal-time (get-universal-time)) 的便捷简写,返回当前时间的九个解码值。

尽管这些函数功能强大,但直接使用它们可能会显得冗长。以下是获取和显示当前时间的方法。

(multiple-value-bind (second minute hour day month year day-of-week)
(get-decoded-time)
(format t "It is now ~2,'0d:~2,'0d:~2,'0d on ~d/~d/~d. Day of week: ~d."
hour minute second month day year day-of-week))
It is now 14:45:02 on 10/26/2023. Day of week: 3.

对于几乎所有实际应用,local-time 库是事实上的标准。它提供了丰富、直观的 API,用于日期时间算术、时区管理和格式化。它抽象了 Universal Time 的复杂性。

Quicklisp 是 Common Lisp 的包管理器。要使用 local-time,您首先需要将其加载到您的 Lisp 镜像(Lisp image)中:

;; This command downloads and loads the library.
;; You only need to run it once per session.
(ql:quickload :local-time)

比较此示例与前一个示例的清晰度。我们可以获取当前时间,为其增加3天10小时,并根据特定模板进行格式化。

(use-package :local-time)
;; Get the current time as a timestamp object
(let* ((now (now))
(future (timestamp+ now 3 :day))
(future (timestamp+ future 10 :hour)))
(format t "Current time: ~a~%" now)
;; format-timestring can produce almost any format you need.
;; The 'nil' argument uses the current timezone.
(format t "Formatted time: ~a~%"
(format-timestring nil now :format '(:long-weekday ", " :long-month " " :day ", " :year " at " :hour12 ":" :min ":" :sec " " :ampm)))
(format t "In 3 days and 10 hours, it will be: ~a~%" future))
Current time: @2023-10-26T14:45:02.123456-04:00
Formatted time: Thursday, October 26, 2023 at 02:45:02 PM
In 3 days and 10 hours, it will be: @2023-10-30T00:45:02.123456-04:00
  • 优先使用 local-time:对于任何应用层代码,local-time 比内置函数更健壮、可读性更强且功能更丰富。
  • 理解 Universal Time:理解 Universal Time 仍然很有价值,因为它是库所基于的可移植基础,并且经常用于文件元数据和其他底层系统。
  • 探索其他库:尽管 local-time 占据主导地位,但仍有其他库如 cl-dates 存在,用于特定需求,例如工作日计算。
  • 时区很复杂:local-time 具有强大的时区支持。在非纯本地的应用中,始终明确指定时区。