本文译者是一位开源理念的坚定支持者,所以本文虽然不是软件,但是遵照开源的精神发布。
本文译者十分愿意与他人分享劳动成果,如果你对我的其他翻译作品或者技术文章有兴趣,可以在如下位置查看现有的作品集:
由于译者水平有限,因此不能保证译文内容准确无误。如果你发现了译文中的错误(哪怕是错别字也好),请来信指出,任何提高译文质量的建议我都将虚心接纳。
systemd.time — 时间与日期规范
"时长"是"时间长度"的简称,又被称为"时间间隔",表示一段时间的长度。 显示为一个空格分隔的带有时间单位的时长序列。例如:
2h 30min
将序列中的每一段加起来就是最终的结果(150分钟)。 注意,时长的显示不受系统本地化设置的影响,永远使用英文时间单位。
systemd 在解析时长字符串(用于赋值)的时候, 接受与时长的显示类似的语法,不同之处在于可以省略空格。 可以理解的时间单位如下:
usec, us, µs
(微秒)msec, ms
(毫秒)seconds, second, sec, s
(秒)minutes, minute, min, m
(分钟)hours, hour, hr, h
(小时)days, day, d
(天)weeks, week, w
(星期)months, month, M
(月)[=30.44天]years, year, y
(年)[=365.25天]如果没有指定时间单位,一般默认为秒,但是偶尔也有例外。
此外,在某些场合还可以接受纳秒单位("ns
", "nsec
")。
注意,时长的赋值不受系统本地化设置的影响,必须只能使用英文时间单位,
不可使用例如"小时/分钟/秒"之类的非英文时间单位。
下面是一些有效的时长字符串实例:
2 h 2hours 48hr 1y 12month 55s500ms 300ms20s 5day
出于测试和验证目的,可以使用 systemd-analyze(1) 的 timespan 命令规范化给定的时长字符串。
时间戳表示的是一个独一无二的时间点, systemd 会按照本地时区格式化之后显示, 例如:
Fri 2012-11-23 23:02:15 CET
注意,时间戳的显示不受系统本地化设置的影响,并且表示"星期"的部分永远使用英文三字母缩写。
有时候,时间戳会以UTC时间(而非本地时间)显示,
此时,将会明确显示 "UTC
" 时区标记。
有时候,时间戳会以微秒精度显示, 此时,表示"秒"的部分将会以带十进制小数的方式显示更精确的亚秒级时间。
systemd 在解析时间戳字符串(用于赋值)的时候,接受与时间戳的显示类似的语法。
不同之处在于:
(1)尾部的"时区"部分,要么必须省略、要么必须丝毫不差的设为"UTC
"三个大写字母、要么必须设为一个符合IANA格式的时区。
省略时区表示使用本机时区、设为"UTC"则表示使用世界统一时间,
使用 timedatectl list-timezones 命令(参见
timedatectl(1) 手册)可以按照IANA格式列出所有时区。
强烈建议使用"UTC"时区以保持最佳的兼容性(主要是为了避免夏令时/冬令时造成的麻烦)。
(2)头部的"星期"部分可以省略(强烈建议省略)。如果一定要指定这部分,
那么必须使用英文三字母缩写(例如"Wed")或英文全称(例如"Wednesday"),大小写无所谓,但是不得使用任何非英文表示法。
(3)"年-月-日"与"时:分:秒"两部分,可以省略二者之一,但是不可全部省略。若省略前者,则表示使用当前日期,若省略后者则表示使用"00:00:00"。
(4)"时:分:秒"部分,可以只省略":秒",相当于使用":00"。
(5)"年-月-日"部分,其中的"年"可以省略为2位数字表示,相当于"20xx"(强烈反对此种用法)。
如果指定的"星期"与"年-月-日"(即使此部分已被省略)与实际不相符, 那么该时间戳将被视为无效。
除了接受上述语法之外,
还可以使用一些时间戳关键字:
"now
" 表示当前时间;
"today
",
"yesterday
", "tomorrow
"
分别表示
今天/昨天/明天的零点(00:00:00)。
除了接受上述语法之外,
还可以使用一些相对时间表示法:
给一个时长(见上文)加上
"+
" 前缀或者 " left
" 后缀(注意有空格),
表示以当前时间为基准向未来前进指定的时长;
给一个时长(见上文)加上
"-
" 前缀
或者 " ago
" 后缀(注意有空格),
表示以当前时间为基准向过去倒退指定的时长;
最后,给一个时长(见上文)加上 "@
"
前缀表示
相对于UNIX时间原点(1970-01-01 00:00:00 UTC)之后多长时间。
假定当前时间为北京时间[UTC+8] 2012-11-23 18:15:22 , 系统时区 TZ=PRC (中华人民共和国的通用时区)。 下面是一些时间戳实例及其标准化形式:
Fri 2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13 2012-11-23 11:12:13 → Fri 2012-11-23 11:12:13 2012-11-23 11:12:13 UTC → Fri 2012-11-23 19:12:13 2012-11-23 → Fri 2012-11-23 00:00:00 12-11-23 → Fri 2012-11-23 00:00:00 11:12:13 → Fri 2012-11-23 11:12:13 11:12 → Fri 2012-11-23 11:12:00 now → Fri 2012-11-23 18:15:22 today → Fri 2012-11-23 00:00:00 today UTC → Fri 2012-11-23 16:00:00 yesterday → Fri 2012-11-22 00:00:00 tomorrow → Fri 2012-11-24 00:00:00 tomorrow Pacific/Auckland → Thu 2012-11-23 19:00:00 +3h30min → Fri 2012-11-23 21:45:22 -5s → Fri 2012-11-23 18:15:17 11min ago → Fri 2012-11-23 18:04:22 @1395716396 → Tue 2014-03-25 03:59:56
注意,不能将其他不同时区的系统所显示的时间戳直接用于赋值。
因为无法识别UTC与本地时区之外的时间戳,所以其他系统所显示的时间戳可能会被错误的解析(除非那个系统的时区正好是"UTC
")。
如果想以更高的微秒精度表示时间戳,"秒"部分可以用带十进制小数的方式表示更精确的亚秒级时间。 例如:
2014-03-25 03:59:56.654563
有时候, systemd 还可能显示相对时间戳(相对于当前时间或命令的调用时间), 例如:
2 months 5 days ago
注意,systemd 显示的相对时间戳可以直接用于赋值(也就是可以被正确解析)。
所谓"日历事件"是指可以同时表达多个时间戳的一种特殊的表达式, 可以把它想象成一种专用于时间戳的正则表达式。 其语法是基于前述绝对时间戳语法的一种扩展。例如:
Thu,Fri 2012-*-1,5 11:12:13
表示: 2012年任意月份的1号或5号 且为周三或周五的日子的11点12分13秒
"星期"部分是可选的。
若指定,
则必须使用英文三字母缩写(例如"Wed")或英文全称(例如"Wednesday"),
大小写无关。可以使用 ",
" 依次列出多个日子,
也可以使用 "..
" 表示一个范围,
还可以将多个范围( "..
" )
用 ",
" 依次列出。
对于"年-月-日"与"时:分:秒"两部分中的
每个子部分,
都可以:
使用 "*
" 表示匹配任意值、
使用 ",
" 依次列出多个值、
使用 "/整数" 后缀表示以此整数为间隔不断向后重复跳跃(例如在表示分钟的部分"3/10"等价于"3,13,23,33,43,53")、
使用 "..
" 表示一个范围。
最后,
还可以用逗号(,)依次列出多个重复(/)与范围(..)。
在日期部分还可以使用 "~
" 表示一个月中的"倒数第几天"。
例如 "*-02~03
" 表示"2月的倒数第3天",
"Mon *-05~07/1
"
表示"5月的最后一个星期一"。
注意,"秒"部分比较特殊, 可以使用十进制小数以表示更高的精度(最多六位小数), 例如"3.33/10.05"等价于"3.33,13.38,23.43,33.48,43.53,53.58"。
若省略了"年-月-日" 则等价于当前日期; 若省略了"时:分:秒"则等价于"00:00:00"; 若省略了":秒"则等价于":00"
"时区"部分遵守与时间戳一样的规则,
要么必须省略、要么必须丝毫不差的设为"UTC
"三个大写字母、要么必须设为一个符合IANA格式的时区。
省略时区表示使用本机时区,为了保持最佳的兼容性,强烈建议使用"UTC"时区(世界统一时间)。
下面这些左侧的特殊表达式可以用作右侧的标准化形式的缩写:
minutely → *-*-* *:*:00 hourly → *-*-* *:00:00 daily → *-*-* 00:00:00 monthly → *-*-01 00:00:00 weekly → Mon *-*-* 00:00:00 yearly → *-01-01 00:00:00 quarterly → *-01,04,07,10-01 00:00:00 semiannually → *-01,07-01 00:00:00
下面是一些日历事件的实例及其 标准化形式:
Sat,Thu,Mon..Wed,Sat..Sun → Mon..Thu,Sat,Sun *-*-* 00:00:00 Mon,Sun 12-*-* 2,1:23 → Mon,Sun 2012-*-* 01,02:23:00 Wed *-1 → Wed *-*-01 00:00:00 Wed..Wed,Wed *-1 → Wed *-*-01 00:00:00 Wed, 17:48 → Wed *-*-* 17:48:00 Wed..Sat,Tue 12-10-15 1:2:3 → Tue..Sat 2012-10-15 01:02:03 *-*-7 0:0:0 → *-*-07 00:00:00 10-15 → *-10-15 00:00:00 monday *-12-* 17:00 → Mon *-12-* 17:00:00 Mon,Fri *-*-3,1,2 *:30:45 → Mon,Fri *-*-01,02,03 *:30:45 12,14,13,12:20,10,30 → *-*-* 12,13,14:10,20,30:00 12..14:10,20,30 → *-*-* 12..14:10,20,30:00 mon,fri *-1/2-1,3 *:30:45 → Mon,Fri *-01/2-01,03 *:30:45 03-05 08:05:40 → *-03-05 08:05:40 08:05:40 → *-*-* 08:05:40 05:40 → *-*-* 05:40:00 Sat,Sun 12-05 08:05:40 → Sat,Sun *-12-05 08:05:40 Sat,Sun 08:05:40 → Sat,Sun *-*-* 08:05:40 2003-03-05 05:40 → 2003-03-05 05:40:00 05:40:23.4200004/3.1700005 → *-*-* 05:40:23.420000/3.170001 2003-02..04-05 → 2003-02..04-05 00:00:00 2003-03-05 05:40 UTC → 2003-03-05 05:40:00 UTC 2003-03-05 → 2003-03-05 00:00:00 03-05 → *-03-05 00:00:00 hourly → *-*-* *:00:00 daily → *-*-* 00:00:00 daily UTC → *-*-* 00:00:00 UTC monthly → *-*-01 00:00:00 weekly → Mon *-*-* 00:00:00 weekly Pacific/Auckland → Mon *-*-* 00:00:00 Pacific/Auckland yearly → *-01-01 00:00:00 annually → *-01-01 00:00:00 *:2/3 → *-*-* *:02/3:00
定时器单元会使用日历事件,详见 systemd.timer(5) 手册。
出于测试和验证目的,可以使用 systemd-analyze(1) 的 calendar 命令规范化给定的日历事件。 此工具还会计算出给定日历事件的下一个过期时间。