Support for ISO 8601 date-time representations

ISO 8601 is an international standard for representing dates in the Gregorian calendar and times and representations of periods of times. (There are descriptions in a number of places. See, for example, ISO 8601 in the Wikipedia Encyclopedia, where you will find additional links. ISO 8601 specifies formats for specifying dates and times. Dates and times are specified with numbers separated and/or delimited with symbols or letters. Here are some strings using ISO 8601 format to specify a date or time:

  • "1985-04-12": the date April 12, 1985. No time specified.
  • "1985-04-12T23:20:50+02:00": same date, but with a time (23:20:50 and a timezone (+2) specified.)
  • "19850412": again April 12, 1985, specified positionally without delimiters.
  • "85-04-12": same date, implied century.
  • "-0019850412": April 12, -1985 (all years, BCE and CE can be specified).

There is much more to say about allowable strings and what can and cannot be left out. There is not space for a full description here. Suffice it to say that any exact, reduced, or truncated representation of a date or time, including fractional seconds, can be represented.

All dates use the Gregorian Calendar, the calendar currently in use almost everywhere on earth, even dates prior to the implementation of the Gregorian Calendar on 15 October 1582. This means that every date can be represented uniquely according to that calendar, but it also means that for dates prior to 15 October 1582, the date given in contemporary sources (say 25 October, 1415, the contemporary source date of the Battle of Agincourt) will be different from the ISO 8601 date.

Another difference between ISO 8601 and what you might expect is ISO 8601 has a year 0. Most other schemes do not.

But enough on the peculiarities of ISO 8601. It is a standard that has wide acceptance and all users will thus refer to comparable dates and times.

Allegro CL now accepts ISO 8601 date/time strings and stores them as Lisp objects. Date-time functionality is included in the datetime module and symbols are in the util.date-time package. The facility is described in date-time.htm.

The generic function util.date-time:date-time takes an ISO 8601 string as an argument and returns a util.date-time:date-time instance. The facility also supports ISO 8601-specified durations (see util.date-time:duration) and time-intervals (see util.date-time:time-interval). One can add and subtract durations to/from date-time objects to create new date-time objects.

Here is a quick example, where only the date is specified. We create a date-time object and apply reader and other functions to it. (If you have downloaded the update, evaluate (require :date-time) before trying to evaluate these and later example forms.)

 > (setq d (util.date-time:date-time "1985-04-12"))
 #<date-time "1985-04-12" @ ...>

 > (util.date-time:date-time-year d)
 1985
 > (util.date-time:date-time-ymd-month d)
 4
 > (util.date-time:date-time-ymd-day d)
 12
 > (util.date-time:date-time-yd-day d)
 102

 ;; Here is DESCRIBE on the date-time instance D.
 ;; Notice that no time information is present as
 ;; none was provided:
 > (describe d)
 #<date-time "1985-04-12" @ ...> is a date-time.
  ymd-yd-before-year-0         nil
  ymd-yd-century               19
  ymd-yd-year-in-century       85
  ymd-month                    4
  ymd-day                      12
  yd-day                       102
  ywd-before-year-0            nil
  ywd-century                  19
  ywd-decade-in-century        8
  ywd-year-in-decade           5
  ywd-week                     15
  ywd-day                      5
  zone-hour                    nil
  zone-minute                  nil
  hour                         nil
  hourf                        nil
  minute                       nil
  minutef                      nil
  second                       nil
  secondf                      nil
 Displayed using various locale-print-time fmts:
  "%Y-%m-%d"                         1985-04-12
 Calendar Date:
  "%Y-%m-%d"                         1985-04-12
 Ordinal Date:
  "%Y-%j"                            1985-102
 Week Date:
  "%G-W%V-%u"                        1985-W15-5
 >

Support is provided for converting between Common Lisp universal times and ISO 8601 date/times. Because any date can be represented in ISO 8601 but only dates after 1900 in universal time, the date-time facility extends the notion of universal time to accept negative values allowing it to represent pre-1900 dates. We also accept fractional values, which allow representing fractional seconds. The function util.date-time:date-time-to-ut converts an ISO 8601 date/time to universal time while util.date-time:ut-to-date-time does the opposite.

 > (setq d (util.date-time:date-time "1985-04-12T23:20:50+02:00"))
 #<date-time "1985-04-12T23:20:50+02:00" @ ...>

 > (setq ut (util.date-time:date-time-to-ut d))
 2691192050

 > (decode-universal-time ut (util.date-time:date-time-zone d))
 50     ; second
 20     ; minute
 23     ; hour
 12     ; day
 4      ; month
 1985   ; year
 4      ; day of week 
 nil    ; daylight savings time
 2      ; timezone
 > (util.date-time:ut-to-date-time ut)
 #<date-time "1985-04-12T23:20:50+02:00" @ ...>
 > 

The new facility is in the datetime module. It is available in an update. Use sys:update-allegro to get the update.

Copyright © 2023 Franz Inc., All Rights Reserved | Privacy Statement Twitter