После прочтения документации encode-time
и decode-time
я не понимаю, как они работают.
Моя проблема связана с тем, что encode-time
возвращает значения два, тогда как я ожидаю только одно (количество секунд с эпохи 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 бит. т.е. реальное количество секунд
(+ (* 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.
Итак, мы видим, что ожидаемый формат — это список со значениями «ВЫСОКИЙ» и «НИЗКИЙ» (и, возможно, дополнительная информация). Следование этому направлению к 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-xelisp-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)))