Contents

以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