> For the complete documentation index, see [llms.txt](https://man.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://man.bsdcn.org/man1/date.1.md).

# date(1)

`date` — 显示或设置日期和时间

## 名称

`date`

## 概要

`date [-nRu] [-z output_zone] [-I[FMT]] [-r filename] [-r seconds] [-v [+|-]val[y|m|w|d|H|M|S]] [+output_fmt]`

`date [-jnRu] [-z output_zone] [-I[FMT]] [-v [+|-]val[y|m|w|d|H|M|S]] [[[[cc]yy]mm]dd]HH[MM[.SS]] [+output_fmt]`

`date [-jnRu] [-z output_zone] [-I[FMT]] [-v [+|-]val[y|m|w|d|H|M|S]] -f input_fmt new_date [+output_fmt]`

## 描述

不带参数调用时，`date` 实用程序显示当前日期和时间。否则，根据指定的选项，`date` 会设置日期和时间，或以用户自定义的方式打印。

`date` 实用程序显示从内核时钟读取的日期和时间。当用于设置日期和时间时，内核时钟和硬件时钟都会更新。

只有超级用户可以设置日期，并且如果系统安全级别（参见 securelevel(7)）大于 1，则时间更改不能超过 1 秒。

选项如下：

**`-f`** `input_fmt` 使用 `input_fmt` 作为格式字符串来解析提供的 `new_date`，而不是使用默认的 `[[[[cc]yy]mm]dd]HH[MM[.SS]]` 格式。解析使用 strptime(3) 完成。

**`-I`**\[`FMT`] 使用扩展的 ISO 8601 输出格式。`FMT` 可以省略，此时默认为 `date`。有效的 `FMT` 值为 `date`、`hours`、`minutes`、`seconds` 和 `ns`（纳秒）。日期和时间格式化为指定的精度。当 `FMT` 为 `hours`（或更精确的 `minutes`、`seconds` 或 `ns`）时，扩展的 ISO 8601 格式包含时区偏移量。

**`-j`** 不尝试设置日期。这允许你将 `-f` 标志与 `+` 选项结合使用，将一种日期格式转换为另一种。请注意，`-f` 格式字符串未指定的任何日期或时间分量都取自当前时间。

**`-n`** 已废弃的标志，为兼容性而接受并忽略。

**`-R`** 使用 RFC 2822 日期和时间输出格式。这等同于在 `LC_TIME` 设置为“C”区域时，使用 `%a, %d %b %Y %T %z` 作为 `output_fmt`。

**`-r`** `seconds` 打印由 `seconds` 表示的日期和时间，其中 `seconds` 是自 Unix 纪元（1970 年 1 月 1 日 00:00:00 UTC；参见 time(3)）以来的秒数，可以用十进制、八进制或十六进制指定。

**`-r`** `filename` 打印 `filename` 最后一次修改的日期和时间。

**`-u`** 以 UTC（协调世界时）显示或设置日期。默认情况下，`date` 显示 **/etc/localtime** 或 `TZ` 环境变量所描述时区的时间。

**`-z`** `output_zone` 在打印时间之前，切换到指定的时区；参见下文对 `TZ` 的描述。这可以与 `-j` 结合使用，方便地将时间规格从一个时区转换到另一个时区。

**`-v`** \[`+`|`-`]`val` \[`y`|`m`|`w`|`d`|`H`|`M`|`S`] 根据 `val` 调整（即取当前日期并显示调整后的结果；不实际设置日期）秒、分、时、月中的日、周中的日、月或年。如果 `val` 前面有加号或减号，日期根据剩余字符串向前或向后调整，否则设置日期的相关部分。可以使用这些标志根据需要多次调整日期。标志按给定顺序处理。设置值（而非调整值）时，秒的范围是 0-59，分的范围是 0-59，小时的范围是 0-23，月中的日的范围是 1-31，周中的日的范围是 0-6（周日到周六），月的范围是 1-12（一月到十二月），年的范围则根据平台有所不同。在 i386 上，年的范围是 69-38，表示 1969-2038。在所有其他平台上，0-68 被接受并表示 2000-2068，69-99 被接受并表示 1969-1999。在两种情况下，100 到 1900（含）之间的年份被接受并解释为相对于格里高利历 1900 年，在 i386 上限制为 138，在其他平台上限制要高得多。从 1901 开始的年份也被接受，并解释为绝对年份。如果 `val` 是数字，必须使用 `y`、`m`、`w`、`d`、`H`、`M` 或 `S` 之一来指定要调整日期的哪一部分。周中的日或月可以使用名称而非数字指定。如果名称与加号（或减号）一起使用，日期将向前（或向后）调整到与给定周中的日或月匹配的下一个（或上一个）日期。如果给定的周中的日或月与当前相同，则不调整日期。当日期被调整为特定值或以大于小时的单位调整时，夏令时考虑被忽略。以小时或更小单位的调整遵守夏令时。因此，假设当前日期是 3 月 26 日 0:30，且夏令时调整意味着时钟在 01:00 前进到 02:00，使用 `-v` +1H 会将日期调整为 3 月 26 日 2:30。同样，如果日期是 10 月 29 日 0:30，且夏令时调整意味着时钟在 02:00 回退到 01:00，使用 `-v` +3H 才能到达 10 月 29 日 2:30。当日期被调整为实际上不存在的特定值（例如欧洲/伦敦时区中 2000 年 3 月 26 日 1:30 BST），日期将以一小时为单位静默向前调整，直到到达有效时间。当日期被调整为出现两次的特定值（例如 2000 年 10 月 29 日 1:30），结果时区将设置为使日期匹配两个时间中较早的一个。无法将日期调整为无效的绝对日，因此使用开关 `-v` 31d `-v` 12m 在一年中有五个月会失败。因此通常先设置月再设置日；使用 `-v` 12m `-v` 31d 总是有效的。按月调整日期本身就有歧义，因为月是一个长度可变的单位，取决于当前日期。这种日期调整以最直观的方式应用。首先，`date` 尝试保留月中的日。如果由于目标月比当前月短而无法保留，则结果为目标月的最后一天。例如，在 5 月 31 日使用 `-v` +1m 会将日期调整为 6 月 30 日，而在 1 月 30 日使用相同选项会将日期调整为 2 月的最后一天。这种方法也被认为对 shell 脚本编写最有意义。不过，请注意，前进和后退相同月数可能会带你到不同的日期。有关更多细节，请参见下面的实例。

以加号（“+”）开头的操作数指定一个用户自定义的格式字符串，用于指定显示日期和时间的格式。格式字符串可以包含 strftime(3) 手册页中描述的任何转换说明，以及任意文本。

支持对常规 strftime(3) 语法的以下扩展：

**`%`**`n``N` 替换为自 Unix 纪元以来秒数的小数部分，取 `n` 位数字。如果 `n` 省略或为零，使用默认值 9，结果是纳秒精度的数字（因此为此转换选择字母“N”）。请注意，底层时钟不一定支持纳秒精度。

**`%-N`** 同上，但根据底层时钟报告的精度自动选择精度。如果指定了 `-r` 选项，则使用默认的 9 位精度。

在格式字符串指定的字符之后，总是会输出一个换行符（`\n`）。默认显示的格式字符串为“%+”。

如果操作数不以加号开头，则被解释为用于设置系统当前日期和时间概念的值。设置日期和时间的规范表示为：

**`cc`** 世纪（19 或 20），前置于缩写年份之前。

**`yy`** 缩写形式的年份（例如 89 表示 1989，06 表示 2006）。

**`mm`** 数字月份，1 到 12 的数字。

**`dd`** 日，1 到 31 的数字。

**`HH`** 小时，0 到 23 的数字。

**`MM`** 分钟，0 到 59 的数字。

**`SS`** 秒，0 到 60 的数字（59 加上可能的闰秒）。

除分钟外，其他均为可选。

`date` 理解位于 **/usr/share/zoneinfo** 中的 IANA 时区数据库 **tzdata** 的时区定义。夏令时、标准时间、闰秒和闰年的时间更改会自动处理。

有两种指定时区的方式：

如果文件或符号链接 **/etc/localtime** 存在，它被解释为时区定义文件，通常位于目录层次结构 **/usr/share/zoneinfo** 中，其中包含来自 **tzdata** 的时区定义。

如果设置了环境变量 `TZ`，其值被解释为时区定义文件的名称，可以是绝对路径，也可以是相对于 **/usr/share/zoneinfo** 中时区定义的相对路径。`TZ` 变量覆盖 **/etc/localtime**。

如果时区定义文件无效，`date` 静默回退到 UTC。

早期版本的 `date` 包含 `-d`（设置夏令时标志）和 `-t`（设置负时区偏移）选项，但这些细节现在由 **tzdata** 自动处理。现代偏移量对于 UTC 之前的时区为正，对于 UTC 之后的时区为负，但与已废弃的 `-t` 选项类似，**/usr/share/zoneinfo/Etc** 子目录中的 **tzdata** 文件仍使用较早的约定，即 UTC 之前的时间被视为负值。

## 环境变量

以下环境变量影响 `date` 的执行：

**`TZ`** 显示日期时使用的时区。常规格式是相对于 **/usr/share/zoneinfo** 的路径名。例如，命令“TZ=America/Los\_Angeles date”显示加利福尼亚的当前时间。该变量也可以指定绝对路径。更多信息请参见 [environ(7)](/man7/environ.7.md)。

## 文件

**/etc/localtime** 默认系统时区的时区信息文件。可以省略，此时默认时区为 UTC。

**/usr/share/zoneinfo** 包含时区信息文件的目录。

**/var/log/messages** 用户设置时间的记录。

**/var/log/utx.log** 日期重置和时间更改的记录。

## 退出状态

`date` 实用程序成功时退出值为 0，无法设置日期时为 1，能够设置本地日期但无法全局设置时为 2。

## 实例

命令

```sh
date +%s.%3N
```

将以毫秒精度打印自 Unix 纪元以来经过的时间。

命令：

```sh
date +DATE: %Y-%m-%d%nTIME: %H:%M:%S
```

将显示：

```sh
DATE: 1987-11-21
TIME: 13:36:16
```

在欧洲/伦敦时区，命令：

```sh
date -v1m -v+1y
```

将显示：

```sh
Sun Jan 4 04:15:24 GMT 1998
```

而当前时间是 `Mon Aug 4 04:15:24 BST 1997`。

命令：

```sh
date -v1d -v3m -v0y -v-1d
```

将显示 2000 年 2 月的最后一天：

```sh
Tue Feb 29 03:18:00 GMT 2000
```

命令：

```sh
date -v3m -v30d -v0y -v-1m
```

也会显示同样的结果，因为 2 月没有 30 日。

命令：

```sh
date -v1d -v+1m -v-1d -v-fri
```

将显示该月最后一个星期五：

```sh
Fri Aug 29 04:31:11 BST 1997
```

而当前时间是 `Mon Aug 4 04:31:11 BST 1997`。

命令：

```sh
date 8506131627
```

将日期设置为 `June 13, 1985, 4:27 PM`。

```sh
date +%Y%m%d%H%M.%S
```

可以用于在一台机器上打印出适合在另一台机器上设置的日期。（在 Linux 上与 GNU date 一起使用 `+%m%d%H%M%Y.%S`。）

命令：

```sh
date 1432
```

将时间设置为 `2:32 PM`，不修改日期。

命令

```sh
TZ=America/Los_Angeles date -Iseconds -r 1533415339
```

将显示

```sh
2018-08-04T13:42:19-07:00
```

命令：

```sh
env LC_ALL=C date -j -f %a %b %d %T %Z %Y `env LC_ALL=C date` +%s
```

可用于解析 `date` 的输出并以纪元时间表示。

最后，命令

```sh
TZ=America/Los_Angeles date -z Europe/Paris -j 0900
```

将在“America/Los\_Angeles”时区为 9:00 时，打印“Europe/Paris”时区的时间。

## 诊断

将 `-I` 标志与 `-R` 或输出格式（“+...”）操作数组合是无效的。如果发生这种情况，`date` 会打印：`multiple output formats specified` 并以状态 1 退出。

## 参见

locale(1), [clock\_gettime(2)](/sys/clock_gettime.2.md), [gettimeofday(2)](/sys/gettimeofday.2.md), [getutxent(3)](/gen/getutxent.3.md), [strftime(3)](/stdtime/strftime.3.md), [strptime(3)](/stdtime/strptime.3.md), [tzset(3)](/stdtime/tzset.3.md), adjkerntz(8), ntpd(8), [tzsetup(8)](/man8/tzsetup.8.md)

> R. Gusella, S. Zatti, "TSP: The Time Synchronization Protocol for UNIX 4.3BSD"。

> "Time Zone Database"。

## 标准

`date` 实用程序预期与 IEEE Std 1003.2 ("POSIX.2") 兼容。除 `-u` 选项外，所有选项都是对标准的扩展。

`-I` 标志选择的格式与 ISO 8601 兼容。

`%N` 纳秒转换说明是非标准扩展。它与 GNU date 的 `%N` 兼容。

## 历史

`date` 命令出现于 Version 1 AT\&T UNIX。

许多选项被添加然后又被移除，包括 `-d`（设置 DST 标志）和 `-t`（设置负时区偏移）。时区现在由与 **tzdata** 一起打包的代码处理。

`-I` 标志在 FreeBSD 12.0 中添加。

`%N` 转换说明在 FreeBSD 14.1 中添加。对 `%nN` 和 `%-N` 变体的支持在 FreeBSD 15.1 中添加。
