Lisp - Date and Time
Lisp - Modern Date and Time Handling
Section titled “Lisp - Modern Date and Time Handling”Handling dates and times is a common requirement in software development. Common Lisp provides a low-level, portable standard for time called Universal Time. For more sophisticated and developer-friendly operations, the modern ecosystem relies on external libraries. This tutorial covers both approaches.
The Foundation: Universal Time
Section titled “The Foundation: Universal Time”Common Lisp’s built-in time functions revolve around Universal Time, an integer representing the number of seconds that have elapsed since midnight, January 1, 1900, GMT.
get-universal-time: Returns the current Universal Time as an integer. This is the primary way to get a timestamp.decode-universal-time: Converts a Universal Time integer into nine values for easier inspection: second, minute, hour, day, month, year, day of the week (Monday=0), a daylight saving time flag, and the timezone offset from GMT.encode-universal-time: Performs the reverse operation, converting the nine decoded values back into a Universal Time integer.get-decoded-time: A convenient shorthand for(decode-universal-time (get-universal-time)), returning the nine decoded values for the current time.
Example: Using Built-in Functions
Section titled “Example: Using Built-in Functions”While powerful, using these functions directly can be verbose. Here’s how to get and display the current 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))Sample Output
Section titled “Sample Output”It is now 14:45:02 on 10/26/2023. Day of week: 3.The Modern Approach: The local-time Library
Section titled “The Modern Approach: The local-time Library”For nearly all practical applications, the local-time library is the de facto standard. It provides a rich, intuitive API for date-time arithmetic, timezone management, and formatting. It abstracts away the complexities of Universal Time.
Installation with Quicklisp
Section titled “Installation with Quicklisp”Quicklisp is the package manager for Common Lisp. To use local-time, you first need to load it into your Lisp image:
;; This command downloads and loads the library.;; You only need to run it once per session.(ql:quickload :local-time)Example: Using local-time
Section titled “Example: Using local-time”Compare the clarity of this example with the previous one. We can get the current time, add 3 days and 10 hours to it, and format it according to a specific template.
(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))Sample Output
Section titled “Sample Output”Current time: @2023-10-26T14:45:02.123456-04:00Formatted time: Thursday, October 26, 2023 at 02:45:02 PMIn 3 days and 10 hours, it will be: @2023-10-30T00:45:02.123456-04:00Best Practices and Further Learning
Section titled “Best Practices and Further Learning”- Prefer
local-time: For any application-level code,local-timeis more robust, readable, and feature-rich than the built-in functions. - Understand Universal Time: It’s still valuable to understand Universal Time, as it’s the portable foundation that libraries are built upon and is often used in file metadata and other low-level systems.
- Explore Other Libraries: While
local-timeis dominant, other libraries likecl-datesexist for specific needs, such as business-day calculations. - Timezones are Complex:
local-timehas powerful timezone support. Always be explicit about timezones in applications that are not purely local.