以DST-SAFE方式获取相对日期
1. 概述
夏令时 是世界上许多地理位置的常见做法。由于它涉及将时钟提前(通常是一小时),因此,在标准时间切换到夏令时的那一天,我们显然会损失一小时。
在本教程中,我们将重点关注以 DST 安全方式获取相对日期的用例。
2. 相对日期
*date *命令是在 Unix 或 Linux 系统上获取日期和时间信息的事实标准。在本节中,我们将学习如何使用自然语言中的单词(例如昨天和明天)获取相对日期。此外,在获取 DST 安全的相对日期时,我们会发现一个微妙的问题。
2.1.基本
让我们首先从 10,000 英尺的角度来了解与使用date命令获取相对日期相关的概念。我们可以使用带*–date选项的yesterday*关键字来获取昨天的日期:
$ date; date --date "yesterday"
Sat Mar 12 10:15:39 PST 2022
Fri Mar 11 10:15:39 PST 2022
我们可以看到输出的默认格式包括日期和时间。
同样,让我们使用tomorrow关键字来获取明天的日期:
$ date; date --date "tomorrow"
Sat Mar 12 10:18:45 PST 2022
Sun Mar 13 11:18:45 PDT 2022
因此,夏令时计划在 2022 年 3 月 13 日凌晨 2 点切换。因此,我们可以注意到明天日期的 PDT 时区。此外,正如预期的那样,与当前时间相比,时间提前了一小时。
如果我们想限制输出只显示日期值,我们可以使用%F格式 :
$ date +%F; date --date "tomorrow" +%F
2022-03-12
2022-03-13
2.2. DST-不安全的相对日期
到目前为止,一切都很好。但是,当当前时间是标准时间一天中的最后一个小时,而未来日期属于夏令时时,事情就会变得混乱:
$ date; date --date='3 days'
Thu Mar 10 23:11:01 PST 2022
Mon Mar 14 00:11:01 PDT 2022
要将输出限制为仅限日期,让我们使用*%F*格式:
$ date +%F; date --date='3 days' +%F
2022-03-10
2022-03-14
我们认为如果今天是 3 月 10 日,那么从现在起的第 3 天将是 3 月 13 日。但是,如果没有时区和时间信息,数学似乎不会加起来。
此外,如果我们尝试获取一个属于标准时间的过去日期,而当前时间是属于夏令时的一天的第一个小时,则会出现类似的不一致:
$ date; date --date='3 days ago'
Mon Mar 14 00:11:01 PDT 2022
Thu Mar 10 23:11:01 PST 2022
和之前一样,当我们使用 %F 格式将输出限制为仅限日期时,问题变得更加突出:
$ date +%F; date --date='3 days ago' +%F
2022-03-14
2022-03-10
让我们学习如何以 DST 安全的方式获取相对日期。
3. 使用 GNU date
问题的根本原因是 GNU date命令(大多数 Linux 发行版上的默认日期实用程序)知道夏令时。因此,在这种情况下,它往往会进行比必要的更复杂的计算。相比之下,相对日期的自然含义是在日期级别进行简单的算术运算,而不用担心一天中的当前时间。
为了解决这个问题,我们可以在获取过去或未来的相对时间时指定一天中的时间。
让我们通过获取未来的相对日期来看看这一点:
$ date; date --date='3 days 00:00'
Thu Mar 10 23:11:01 PST 2022
Sun Mar 13 00:00:00 PDT 2022
现在,当我们使用*%F*格式来获取日期时,它与相对日期的自然概念非常吻合:
$ date +%F; date --date='3 days 00:00' +%F
2022-03-10
2022-03-13
同样,我们可以得到过去的相对日期:
$ date; date --date='3 days ago 00:00'
Mon Mar 14 00:11:01 PDT 2022
Fri Mar 11 00:00:00 PST 2022
如前所述,我们可以安全地包含*%F*格式来获取 DST 安全日期值:
$ date +%F; date --date='3 days ago 00:00' +%F
2022-03-14
2022-03-11
4. 使用BSD date
正如我们在上一节中提到的,在大多数 Linux 发行版中,GNU日期是默认的日期实用程序。但是,某些现代操作系统(例如 macOS)使用 BSD 版本作为默认date 实用程序。
在获取相对日期方面,BSD 版本的date命令似乎比基于 GNU 的date命令更智能。通过使用-v*标志,用户始终获得 DST 安全日期。*
让我们看看如何使用*-v*标志来获取从 2022 年 3 月 13 日开始遵守夏令时的洛杉矶时区的未来日期:
$ TZ="America/Los_Angeles" date; TZ="America/Los_Angeles" date -v+1d;
Sat Mar 12 23:11:01 PST 2022
Sun Mar 13 23:11:01 PDT 2022
我们可以注意到,虽然时区信息从 PST 变为 PDT,但时间值与当前时间保持一致。因此,BSD date实用程序在内部调整了一小时时钟提前。
因此,当使用*-v标志使用 BSD date命令获取相对日期时,我们可以安全地使用%F*格式:
$ TZ="America/Los_Angeles" date +%F; TZ="America/Los_Angeles" date -v+1d +%F;
2022-03-12
2022-03-13