42.7 Time Conversion

These functions convert time values (see Time of Day) to Lisp timestamps, or into calendrical information and vice versa.

Many operating systems use 64-bit signed integers to count seconds, and can represent times far in the past or future. However, some are more limited. For example, old-fashioned operating systems that use 32-bit signed integers typically handle only times from 1901-12-13 20:45:52 through 2038-01-19 03:14:07 Universal Time.

Calendrical conversion functions use the Gregorian calendar even for dates before the Gregorian calendar was introduced, and for dates in the far distant past or future for which the Gregorian calendar is wildly inaccurate and disagrees with common practice in scientific fields like astronomy and paleontology, which use Julian-calendar year lengths. Year numbers count since the year 1 BCE, and do not skip zero as traditional Gregorian years do; for example, the year number −37 represents the Gregorian year 38 BCE.

Function: time-convert time form

This function converts a time value into a Lisp timestamp.

The form argument specifies the timestamp form to be returned. If form is the symbol integer, this function returns an integer count of seconds. If form is a positive integer, it specifies a clock frequency and this function returns an integer-pair timestamp (ticks . form). If form is t, this function treats it as a positive integer suitable for representing the timestamp; for example, it is treated as 1000000000 if time is nil and the platform timestamp has nanosecond resolution. If form is list, this function returns an integer list (high low micro pico). Although a nil form currently acts like list, this is planned to change in a future Emacs version, so callers requiring list timestamps should pass list explicitly.

If time is not a time value, this function signals an error. Otherwise, if time cannot be represented exactly, conversion truncates it toward minus infinity. When form is t, conversion is always exact so no truncation occurs, and the returned clock resolution is no less than that of time. By way of contrast, although float-time can also convert any time value without signaling an error, the result might not be exact. See Time of Day.

For efficiency this function might return a value that is eq to time, or that otherwise shares structure with time.

Although (time-convert nil nil) is equivalent to (current-time), the latter may be a bit faster.

(setq a (time-convert nil t))
⇒ (1564826753904873156 . 1000000000)
(time-convert a 100000)
⇒ (156482675390487 . 100000)
(time-convert a 'integer)
⇒ 1564826753
(time-convert a 'list)
⇒ (23877 23681 904873 156000)
Function: decode-time &optional time zone form

This function converts a time value into calendrical information. If you don’t specify time, it decodes the current time, and similarly zone defaults to the current time zone rule. See Time Zone Rules. The operating system limits the range of time and zone values.

The form argument controls the form of the returned seconds element, as described below. The return value is a list of nine elements, as follows:

(seconds minutes hour day month year dow dst utcoff)

Here is what the elements mean:

seconds

The number of seconds past the minute, with form described below.

minutes

The number of minutes past the hour, as an integer between 0 and 59.

hour

The hour of the day, as an integer between 0 and 23.

day

The day of the month, as an integer between 1 and 31.

month

The month of the year, as an integer between 1 and 12.

year

The year, an integer typically greater than 1900.

dow

The day of week, as an integer between 0 and 6, where 0 stands for Sunday.

dst

t if daylight saving time is effect, nil if it is not in effect, and −1 if this information is not available.

utcoff

An integer indicating the Universal Time offset in seconds, i.e., the number of seconds east of Greenwich.

The seconds element is a Lisp timestamp that is nonnegative and less than 61; it is less than 60 except during positive leap seconds (assuming the operating system supports leap seconds). If the optional form argument is t, seconds uses the same precision as time; if form is integer, seconds is truncated to an integer. For example, if time is the timestamp (1566009571321 . 1000), which represents 2019-08-17 02:39:31.321 UTC on typical systems that lack leap seconds, then (decode-time time t t) returns ((31321 . 1000) 39 2 17 8 2019 6 nil 0), whereas (decode-time time t 'integer) returns (31 39 2 17 8 2019 6 nil 0). If form is omitted or nil, it currently defaults to integer but this default may change in future Emacs releases, so callers requiring a particular form should specify form.

Common Lisp Note: Common Lisp has different meanings for dow, dst and utcoff, and its second is an integer between 0 and 59 inclusive.

To access (or alter) the elements in the calendrical information, the decoded-time-second, decoded-time-minute, decoded-time-hour, decoded-time-day, decoded-time-month, decoded-time-year, decoded-time-weekday, decoded-time-dst and decoded-time-zone accessors can be used.

Function: encode-time time &rest obsolescent-arguments

This function converts time to a Lisp timestamp. It can act as the inverse of decode-time.

Ordinarily the first argument is a list (second minute hour day month year ignored dst zone) that specifies a decoded time in the style of decode-time. For the meanings of these list elements, see the table under decode-time. In particular, dst says how to interpret timestamps during a daylight saving fallback when timestamps are repeated. If dst is −1, the DST value is guessed; if it is t or nil the timestamp with that DST value is returned, with an error signaled if no such timestamp exists. Unfortunately a dst value of t or nil does not disambiguate timestamps duplicated when a TZDB-based timezone moves further west of Greenwich, such as disambiguating the two standard-time timestamps 2020-12-27 01:30 when zone is ‘"Europe/Volgograd"’, which at 02:00 that day changed standard time from 4 to 3 hours east of Greenwich; if you need to handle situations like this you can use a numeric zone to disambiguate instead.

The first argument can also be a list (second minute hour day month year), which is treated like the list (second minute hour day month year nil -1 nil).

As an obsolescent calling convention, this function can be given six or more arguments. The first six arguments second, minute, hour, day, month, and year specify most of the components of a decoded time. If there are more than six arguments the last argument is used as zone and any other extra arguments are ignored, so that (apply #'encode-time (decode-time ...)) works. In this obsolescent convention, dst is −1 and zone defaults to the current time zone rule (see Time Zone Rules). When modernizing an obsolescent caller, ensure that the more-modern list equivalent contains 9 elements with a dst element that is −1, not nil.

Year numbers less than 100 are not treated specially. If you want them to stand for years above 1900, or years above 2000, you must alter them yourself before you call encode-time. The operating system limits the range of time and zone values. However, timestamps ranging from the epoch to the near future are always supported.

The encode-time function acts as a rough inverse to decode-time. For example, you can pass the output of the latter to the former as follows:

(encode-time (decode-time …))

You can perform simple date arithmetic by using out-of-range values for seconds, minutes, hour, day, and month; for example, day 0 means the day preceding the given month. Take care when doing so, as it is common for this to fail in some cases. For example:

;; Try to compute the time one month from now.
;; Watch out; this might not work as expected.
(let ((time (decode-time)))
  (setf (decoded-time-month time)
        (+ (decoded-time-month time) 1))
  time)

Unfortunately, this code might not work as expected if the resulting time is invalid due to month length differences, daylight saving transitions, time zone changes, or missing leap days or leap seconds. For example, if executed on January 30 this code yields a nonexistent date February 30, which encode-time would adjust to early March. Similarly, adding four years to February 29, 2096 would yield the nonexistent date February 29, 2100; and adding one hour to 01:30 on March 13, 2022 in New York would yield a timestamp 02:30 that does not exist because clocks sprang forward from 02:00 to 03:00 that day. To avoid some (though not all) of the problem, you can base calculations on the middle of the affected unit, e.g., start at the 15th of the month when adding months. Alternatively, you can use the calendar and time-date libraries.