43.8 时间解析与格式化

这些函数将时间值转换为文本字符串,反之亦然。时间值可以表示为 Lisp 时间戳(see 时刻)或解码时间结构(see 时间转换)。

Function: date-to-time string

该函数解析时间字符串 string,并返回对应的 Lisp 时间戳。参数 string 应当表示一个日期时间,且格式需为 parse-time-string 能识别的格式(见下文)。如果 string 缺少明确的时区信息,该函数默认使用协调世界时;如果 string 缺少月份、日期或时间部分,则默认使用最小有效值。操作系统会限制时间和时区值的范围。

Function: parse-time-string string

该函数将时间字符串 string 解析为解码时间结构(see 时间转换)。参数 string 应当类似 RFC 822(或更高版本)或 ISO 8601 格式的字符串,例如 “Fri, 25 Mar 2016 16:24:56 +0100” 或 “1998-09-12T12:21:54-0200”,但该函数也会尝试解析格式不太规范的时间字符串。

注意,与 decode-time(see 时间转换)不同,该函数 不会解释 时间字符串;具体来说,参数 string 中的夏令时、时区或 UTC 偏移量不会影响返回的日期时间值,仅会影响返回的解码时间结构的最后两个成员。例如,如果 string 中包含时区信息,解码时间结构会包含该信息;否则返回值的时区成员为 nil。换言之,该函数仅将日期时间的文本表示解析为独立的数值,不关心输入时间是本地时间还是 UTC 时间。

如果 Lisp 程序将该函数的返回值传递给其他与时间相关的 API,应确保正确解释解码时间结构中的 nil 成员;特别是缺少时区信息时,需根据调用程序的需求将其解释为 UTC 或本地时间。

Function: iso8601-parse string

对于更严格的函数(输入无效时会报错),Lisp 程序可以使用该函数替代。它能解析 ISO 8601 标准的所有变体,因此除了上述格式外,还能解析 “1998W45-3”(周号)和 “1998-245”(序数日期)等格式。解析时长使用 iso8601-parse-duration,解析时间间隔使用 iso8601-parse-interval。所有这些函数都返回解码时间结构,最后一个除外,它返回三个结构(开始时间、结束时间和时长)。

parse-time-string 相同,该函数不会解释时间字符串;参数 string 中的时区标识或 UTC 偏移量不会影响返回的日期时间值,仅影响返回的解码时间结构的最后两个成员。ISO 8601 标准规定,不包含 UTC 关系信息的日期时间字符串默认为本地时间,但该函数不会这样处理,因为它不解释时间值。例如,如果 string 中包含时区信息,解码时间结构会包含该信息;否则返回值的时区成员为 nil。换言之,该函数仅将日期时间的文本表示解析为独立的数值,不关心输入时间是本地时间还是 UTC 时间。

Function: format-time-string format-string &optional time zone

该函数根据格式字符串 format-string,将时间 time(应为 Lisp 时间戳,若省略或为 nil 则默认为当前时间)转换为字符串。转换使用时区规则 zone,默认为当前时区规则。see 时区规则。参数 format-string 可以包含 ‘%’ 序列,用于替换时间的各个部分。以下是 ‘%’ 序列的含义对照表:

%a

星期的缩写名称。

%A

星期的完整名称。

%b

月份的缩写名称。

%B

月份的完整名称。

%c

等价于 ‘%x %X’。

%C

世纪,即年份除以 100 并向零取整。默认字段宽度为 2。

%d

日期,补前导零。

%D

等价于 ‘%m/%d/%y’。

%e

日期,补前导空格。

%F

ISO 8601 日期格式,类似于 ‘%+4Y-%m-%d’,但任何标志或字段宽度会覆盖 ‘+’ 和(减 6 后)‘4’。

%g

对应当前 ISO 周 号的年份(不含世纪,00–99)。ISO 周从星期一开始,星期日结束。如果一个 ISO 周始于某一年而止于另一年,‘%g’ 对应的年份规则较为复杂,此处不赘述;但通常情况下,如果一周的大部分天数属于结束的那一年,‘%g’ 就会输出该年份。

%G

对应当前 ISO 周号的年份(含世纪)。

%h

等价于 ‘%b’。

%H

小时(00–23)。

%I

小时(01–12)。

%j

一年中的第几天(001–366)。

%k

小时(0–23),补前导空格。

%l

小时(1–12),补前导空格。

%m

月份(01–12)。

%M

分钟(00–59)。

%n

换行符。

%N

纳秒(000000000–999999999)。如需更少位数,使用 ‘%3N’ 表示毫秒,‘%6N’ 表示微秒,依此类推。多余位数直接丢弃,不四舍五入。

%p

上午(AM)或下午(PM)。

%q

季度(1–4)。

%r

等价于 ‘%I:%M:%S %p’。

%R

等价于 ‘%H:%M’。

%s

自纪元起的总秒数(整数)。

%S

秒数(00–59,支持闰秒的平台为 00–60)。

%t

制表符。

%T

等价于 ‘%H:%M:%S’。

%u

数字表示的星期(1–7),星期一为 1。

%U

一年中的第几周(01–52),默认星期为一周的开始。如果 1 月 1 日不是星期日,第一个不完整的周为第 0 周。

%V

ISO 8601 标准的一年中的第几周。注意,与 ‘%U’ 和 ‘%W’ 不同,ISO 8601 的周数在 1 月 1 日 不会 重置为 1,而是延续上一年的周数。

%w

数字表示的星期(0–6),星期日为 0。

%W

一年中的第几周(01–52),默认星期一为一周的开始。如果 1 月 1 日不是星期一,第一个不完整的周为第 0 周。

%x

与区域设置相关。默认区域(‘C’)下等价于 ‘%D’。

%X

与区域设置相关。默认区域(‘C’)下等价于 ‘%T’。

%y

年份(不含世纪,00–99)。

%Y

年份(含世纪)。

%Z

时区缩写(例如 ‘EST’)。

%z

时区数字偏移量。‘z’ 前可以加一个、两个或三个冒号;如果普通 ‘%z’ 表示 ‘-0500’,那么 ‘%:z’ 表示 ‘-05:00’,‘%::z’ 表示 ‘-05:00:00’,‘%:::z’ 与 ‘%::z’ 类似,但会省略末尾的 ‘:00’,例如表示为 ‘-05’。

%%

表示一个字面量 ‘%’。

一个或多个标志字符可以直接出现在 ‘%’ 之后: ‘0’ 补零,‘+’ 补零且对四位以上的非负年份添加前导加号,‘_’ 补空格,‘-’ 取消填充,‘^’ 转换为大写,‘#’ 反转大小写。

你还可以为这些 ‘%’ 序列指定字段宽度和填充类型,用法与 printf 相同:在标志之后、‘%’ 序列中用数字表示字段宽度。例如,‘%S’ 表示分钟内的秒数;‘%03S’ 表示补零至 3 位,‘%_3S’ 表示补空格至 3 位。普通的 ‘%3S’ 默认补零,因为 ‘%S’ 通常补零至 2 位。

字符 ‘E’ 和 ‘O’ 可以在标志和字段宽度之后作为修饰符使用。‘E’ 表示使用当前区域设置的替代日期时间格式。例如,在日语区域中,%Ex 可能会生成基于日本天皇年号的日期格式。‘E’ 可用于 ‘%Ec’、‘%EC’、‘%Ex’、‘%EX’、‘%Ey’ 和 ‘%EY’。

O’ 表示使用当前区域设置的替代数字表示,而非普通十进制数字。大多数输出数字的格式都支持该修饰符。

为便于调试程序,无法识别的 ‘%’ 序列会原样输出。程序不应依赖此行为,因为未来版本的 Emacs 可能会将新的 ‘%’ 序列作为扩展功能支持。

该函数使用 C 库函数 strftime(see Formatting Calendar Time in The GNU C Library Reference Manual)完成大部分工作。为与该函数通信,它首先将 timezone 转换为内部格式;操作系统会限制时间和时区值的范围。该函数还会使用 locale-coding-system 指定的编码系统对 format-string 进行编码(see 区域设置);在 strftime 返回结果字符串后,该函数使用相同的编码系统对字符串进行解码。

Function: format-seconds format-string seconds

该函数根据格式字符串 format-string,将参数 seconds 转换为包含年、天、小时等的字符串。参数 format-string 可以包含 ‘%’ 序列,用于控制转换格式。以下是 ‘%’ 序列的含义对照表:

%y
%Y

按 365 天计算的整数年数。大写格式同时输出单位。

%d
%D

整数天数。大写格式同时输出单位。

%h
%H

整数小时数。大写格式同时输出单位。

%m
%M

整数分钟数。大写格式同时输出单位。

%s
%S

秒数。如果使用可选的 ‘,’ 参数,则为浮点数,‘,’ 后的数字指定小数位数。‘%,2s’ 表示“保留两位小数”。大写格式同时输出单位。

%z

非打印控制标志。使用时,其他格式符必须按单位从大到小的顺序排列,即年在天前、小时在分钟前等。遇到第一个非零转换结果之前,‘%z’ 左侧的内容不会输出到结果字符串中。例如,emacs-uptime(see emacs-uptime)使用的默认格式 "%Y, %D, %H, %M, %z%S" 表示:秒数总会显示,而年、天、小时、分钟仅在非零时才显示。

%x

非打印控制标志,与 ‘%z’ 类似,但用于抑制 末尾零值 时间元素的输出。

%%

输出字面量 ‘%’。

大写格式序列会同时输出数值和单位,小写格式仅输出数值。

你还可以在 ‘%’ 后加数字指定字段宽度,较短的数字会补空格;宽度前加句点表示补零。例如,"%.3Y" 可能输出 "004 years"