了解 `decode-time` 的返回值 (elisp)

Understanding the returned value of `decode-time` (elisp)

阅读 encode-timedecode-time 的文档后,我不明白它们是如何工作的。

我的麻烦来自 encode-time returns 两个 值,而我只期望一个(自UNIX 时代)。这两个值到底是什么意思?

ELISP> (encode-time 0 0 0 1 1 1970 t)
(0 0)
ELISP> (encode-time 0 0 0 1 1 1971 t)
(481 13184)

我更加困惑了,因为这三个调用有效,但我不明白如何解释前两种情况下的参数:

;; Ok this is what I expect from the documentation
ELISP> (decode-time
        (encode-time 0 0 0 1 1 1971 t))
(0 0 0 1 1 1971 5 nil 0)

;; This is also what I expected, given it's the same than above, but I don't understand the meaning of the arguments
ELISP> (decode-time '(481 13184))
(0 0 0 1 1 1971 5 nil 0)

;; I kind of understand the following: here 481  is considered the seconds since UNIX epoch,
;; and 13184 is the difference in seconds from UTC.
;; The returned value, is the date (UNIX epoch + 481 seconds)
;; expressed in a timezone 13184 seconds ahead of UTC (45 47 3 1 1 1970 = 13665 seconds
;; and 13665−13184 = 481) 
ELISP> (decode-time 481 13184)
(45 47 3 1 1 1970 4 nil 13184)

请注意,对于上面的所有示例,我都设置了 (set-time-zone-rule t) 以避免必须处理时区。

(481 131184)表示秒数为(HIGH LOW),其中HIGH为高位,LOW为低16位。 IE。实际秒数是

(+ (* 481 65536) 13184) == 31536000

查看文档:

(decode-time &optional TIME ZONE)

Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF). The optional TIME should be a list of (HIGH LOW . IGNORED), as from ‘current-time’ and ‘file-attributes’, or nil to use the current time. It can also be a single integer number of seconds since the epoch. The obsolete form (HIGH . LOW) is also still accepted.

所以我们可以看到预期的格式是一个包含值 "HIGH" 和 "LOW" 的列表(可能还有一些额外信息)。按照 current-time 的方向给我们进一步的解释:

(current-time)

Return the current time, as the number of seconds since 1970-01-01 00:00:00. The time is returned as a list of integers (HIGH LOW USEC PSEC). HIGH has the most significant bits of the seconds, while LOW has the least significant 16 bits. USEC and PSEC are the microsecond and picosecond counts.

为什么 Emacs 使用这种看似复杂的格式?毫无疑问,答案很简单,就是 Emacs 太老了,它需要在只有 16 位整数可用的系统上工作。

查看手册,M-x elisp-index-search for current-time 将我们带到 (elisp)Time of Day:

Most of these functions represent time as a list of four integers ‘(SEC-HIGH SEC-LOW MICROSEC PICOSEC)’. This represents the number of seconds from the “epoch” (January 1, 1970 at 00:00 UTC), using the formula: HIGH * 2**16 + LOW + MICRO * 10**−6 + PICO * 10**−12. The return value of ‘current-time’ represents time using this form, as do the timestamps in the return values of other functions such as ‘file-attributes’ (*note Definition of file-attributes::). In some cases, functions may return two- or three-element lists, with omitted MICROSEC and PICOSEC components defaulting to zero.

Function arguments, e.g., the TIME argument to ‘current-time-string’, accept a more-general “time value” format, which can be a list of integers as above, or a single number for seconds since the epoch, or ‘nil’ for the current time. You can convert a time value into a human-readable string using ‘current-time-string’ and ‘format-time-string’, into a list of integers using ‘seconds-to-time’, and into other forms using ‘decode-time’ and ‘float-time’. These functions are described in the following sections.

因此,例如,您可以将单个 32 位 Unix 时间戳整数传递给 decode-time

(decode-time 1554670400)
=> (20 53 8 8 4 2019 1 nil 43200)

您也可以使用format-time-string获取单个整数值:

(string-to-number (format-time-string "%s" (current-time)))