如何换算 Unix 时间戳和日期(互转)
将 Unix 纪元秒数转换为任何时区的人类可读日期。附实际示例。
什么是 Unix 时间戳?
Unix 时间戳(也称为 Unix time、POSIX time 或 epoch time)是从 1970 年 1 月 1 日 UTC 00:00:00 起经过的秒数,不包括闰秒。这一刻被称为 Unix 纪元。
例如:
- 0 = 1970-01-01 00:00:00 UTC(纪元)
- 1,000,000,000 = 2001-09-09 01:46:40 UTC("十亿秒")
- 1,234,567,890 = 2009-02-13 23:31:30 UTC
- 1,700,000,000 = 2023-11-14 22:13:20 UTC
- 2,000,000,000 = 2033-05-18 03:33:20 UTC
Unix 时间戳在计算中无处不在:
- 数据库:PostgreSQL、MySQL 和 SQLite 内部都把时间存储为 Unix 时间戳(或以其为参考)。
- 文件系统:ext4、NTFS 和 APFS 把文件修改时间存储为 Unix 时间戳。
- API:JSON API 通常以整数形式返回时间戳,例如 `"created_at": 1700000000`。
- 日志:大多数日志系统以 Unix 格式发出时间戳。
- 编程语言:PHP、Python、JavaScript、Go、Rust 和 Java 都有内置支持。
Unix 时间戳流行的原因是:它们是简单的整数,易于比较、排序、与时区无关(始终指 UTC)并且易于存储。它们也使算术简单 —— 要找到两个事件的持续时间,相减它们的时间戳即可。
如何读 Unix 时间戳
心理模型:想象一个从 1970 年 1 月 1 日 UTC 午夜开始滴答的时钟,此后一直在计数秒数。Unix 时间戳就是那个时钟的读数。
``` 1 分钟 = 60 秒 1 小时 = 3,600 秒 1 天 = 86,400 秒 (24 × 60 × 60) 1 周 = 604,800 秒 (7 × 86,400) 1 年 ≈ 31,536,000 秒 (平均 365.25 × 86,400) 1 十年 ≈ 315,360,000 秒 ```
一些心算锚点:
- 1,000,000,000 = 2001-09-09。Unix 十亿秒 —— 第一个 10 位数的秒。
- 1,500,000,000 = 2017-07-14。"15 亿" 标记。
- 2,000,000,000 = 2033-05-18。第一个 20 亿秒日期。
- 2038 问题:32 位有符号整数在 2,147,483,647 处溢出,即 2038-01-19 03:14:07 UTC。之后,32 位 Unix 时间戳会环绕到负值。
精确换算公式
时间戳转人类日期
``` human_date = epoch + timestamp 秒(UTC) local_date = human_date 转换为本地时区 ```
在大多数编程语言中:
```python import datetime ts = 1700000000 utc = datetime.datetime.fromtimestamp(ts, tz=datetime.timezone.utc) # 2023-11-14 22:13:20+00:00 local = datetime.datetime.fromtimestamp(ts) # 取决于你的系统时区 ```
```js const ts = 1700000000; const date = new Date(ts * 1000); // JS 使用毫秒 // 2023-11-14T22:13:20.000Z ```
人类日期转时间戳
``` timestamp = (date - epoch) 的秒数 ```
```python import datetime d = datetime.datetime(2023, 11, 14, 22, 13, 20, tzinfo=datetime.timezone.utc) ts = int(d.timestamp()) # 1700000000 ```
```js const d = new Date("2023-11-14T22:13:20Z"); const ts = Math.floor(d.getTime() / 1000); // 1700000000 ```
常见时区偏移(相对于 UTC)
处理时间戳时,你经常需要以特定时区显示:
| 时区 | 缩写 | 偏移 | 示例城市 | |------------------------------|--------|-----------------|----------------------------| | 协调世界时 | UTC | 0 | 伦敦(冬),雷克雅未克 | | 美国东部标准时间 | EST | UTC−5 | 纽约(冬) | | 美国东部夏令时 | EDT | UTC−4 | 纽约(夏) | | 太平洋标准时间 | PST | UTC−8 | 洛杉矶(冬) | | 太平洋夏令时 | PDT | UTC−7 | 洛杉矶(夏) | | 中欧时间 | CET | UTC+1 | 巴黎(冬),柏林 | | 中欧夏令时 | CEST | UTC+2 | 巴黎(夏),柏林 | | 日本标准时间 | JST | UTC+9 | 东京 | | 中国标准时间 | CST | UTC+8 | 北京、上海 | | 印度标准时间 | IST | UTC+5:30 | 孟买、德里 | | 澳大利亚东部标准时间 | AEST | UTC+10 | 悉尼(冬) | | 澳大利亚东部夏令时 | AEDT | UTC+11 | 悉尼(夏) |
注意:一些国家(印度、中国)全年采用单一偏移,不实行夏令时。
方法一:使用 UtilBoxx 时间换算工具(推荐)
在浏览器中换算 Unix 时间戳最快、最私密、最准确的方式是 UtilBoxx 时间换算工具。它支持秒和毫秒,在任何时区显示,并显示相应的 ISO 8601 日期、UTC 和本地时间。所有计算在浏览器本地完成 —— 没有服务器、没有上传、没有日志。
使用方法:
- 打开 utilboxx.com/zh/tools/unit/time
- 输入 Unix 时间戳(以秒为单位)或日期字符串
- 换算后的值立即出现
- 一次点击即可切换时区
- 复制结果
为什么推荐这个方法:
- 100% 免费,无注册、无邮箱、无广告
- 隐私优先:不离开你的浏览器
- 双向:时间戳 ↔ 日期任一方向
- 多时区:在 UTC、本地时区或任何时区查看你的时间戳
- 处理毫秒,用于 JavaScript 风格的时间戳
- 任何有浏览器的设备都能用
如果你使用存储时间为 Unix 时间戳的 API、日志或数据库,这个工具第一周就值回票价。
方法二:Python(datetime 模块)
Python 的 `datetime` 模块是时间戳换算的规范工具。两个关键函数是 `fromtimestamp()` 和 `timestamp()`。
```python import datetime from zoneinfo import ZoneInfo
# 时间戳转日期(UTC) ts = 1700000000 utc_date = datetime.datetime.fromtimestamp(ts, tz=datetime.timezone.utc) # 2023-11-14 22:13:20+00:00
# 时间戳转特定时区的日期 ny_tz = ZoneInfo("America/New_York") ny_date = datetime.datetime.fromtimestamp(ts, tz=ny_tz) # 2023-11-14 17:13:20-05:00
# 日期转时间戳 d = datetime.datetime(2023, 11, 14, 22, 13, 20, tzinfo=datetime.timezone.utc) ts = int(d.timestamp()) # 1700000000
# 现在:当前时间戳 now_ts = int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
# 将日期格式化为 ISO 8601 print(utc_date.isoformat()) # 2023-11-14T22:13:20+00:00 ```
Python 3.9+ 也有更简单的 `datetime.fromtimestamp(ts, tz=UTC)` 形式,`zoneinfo` 模块(取代较老的 `pytz`)使时区处理变得简单。
方法三:Bash / 命令行
macOS 和 Linux 上的 `date` 命令既可以解析也可以发出 Unix 时间戳。
```bash # 将 Unix 时间戳转换为人类可读的日期(macOS / BSD) date -r 1700000000 # Tue Nov 14 22:13:20 UTC 2023
# 将 Unix 时间戳转换(Linux / GNU date) date -d @1700000000 # Tue Nov 14 22:13:20 UTC 2023
# 获取当前 Unix 时间戳 date +%s # 1700000000(或其他当前值)
# 将日期字符串转换为 Unix 时间戳(GNU) date -d "2023-11-14 22:13:20 UTC" +%s # 1700000000
# 将日期字符串转换为 Unix 时间戳(macOS) date -j -f "%Y-%m-%d %H:%M:%S" "2023-11-14 22:13:20" +%s # 1700000000
# 以特定时区显示 TZ="America/New_York" date -d @1700000000 # Tue Nov 14 17:13:20 EST 2023 ```
macOS 和 Linux 之间的语法不同。在 macOS 上,`-r` 读取时间戳;在 Linux 上,`-d @...` 读取时间戳,`-d "..."` 解析日期。对于脚本编写,GNU 形式(Linux)更友好;macOS 形式更繁琐但能用。
方法四:JavaScript(在浏览器或 Node.js 中)
JavaScript 对 Unix 时间戳使用毫秒而非秒。从秒转到毫秒时乘以 1,000。
```js // 当前时间戳(毫秒) const now = Date.now(); // 例如,1700000000000
// 将秒转换为毫秒并创建 Date const ts = 1700000000; const date = new Date(ts * 1000); // 2023-11-14T22:13:20.000Z
// 使用 Intl 在特定时区显示 console.log(date.toLocaleString("en-US", { timeZone: "America/New_York" })); // 11/14/2023, 5:13:20 PM
// 显示为 ISO 8601 console.log(date.toISOString()); // 2023-11-14T22:13:20.000Z
// 将日期转换为时间戳(秒) const d = new Date("2023-11-14T22:13:20Z"); const ts2 = Math.floor(d.getTime() / 1000); // 1700000000
// 解析各种格式 new Date("2023-11-14"); // UTC 午夜 new Date("2023-11-14T22:13:20Z"); // 22:13:20 UTC new Date(1700000000 * 1000); // 从毫秒 new Date("Nov 14, 2023 22:13:20");// 区域相关解析(避免!) ```
JavaScript 的 `Date` 对象是出了名的诡异。对于严肃的工作,使用 `date-fns`、`Luxon` 或 `Day.js` 这样的库。对于快速换算,内置的 `Date` 没问题。
常见问题
为什么 Unix 纪元是 1970 年 1 月 1 日?
这是 Unix 操作系统首次实现的日期。Ken Thompson 和 Dennis Ritchie 在 1969-1970 年于贝尔实验室设计 Unix 时随意选择了它。没有天文或数学上的原因;这只是他们工作时十年的开始。其他几个系统选择了不同的纪元:Windows FILETIME 使用 1601 年 1 月 1 日;macOS HFS+ 使用 1904 年 1 月 1 日;GPS 使用 1980 年 1 月 6 日。
什么是 2038 问题?
2038 问题(也称为 Y2K38)是发生在 2038 年 1 月 19 日 UTC 03:14:07 的 32 位有符号整数溢出。32 位有符号整数最大可容纳 2,147,483,647。一秒后,它溢出到 −2,147,483,648,被解释为 1901-12-13 20:45:52 UTC。任何仍在使用 32 位 Unix 时间戳的系统(主要是嵌入式设备、旧数据库和某些文件系统)若不更新就会崩溃。
修复方法很直接:切换到 64 位整数,将 Unix 时间戳范围延长 2900 亿年。大多数现代系统已经这样做了;问题主要在于遗留和嵌入式系统。
Unix 时间戳是秒还是毫秒?
取决于语言:
- 秒:C、Python、Go、Rust、Java(传统上)、shell、SQL
- 毫秒:JavaScript、Java(java.time.Instant)、某些数据库
JavaScript 是使用毫秒的主要异类,这导致当 JavaScript 代码与其他语言的代码混合时会出现 bug。请始终澄清单位。UtilBoxx 换算器通过单一开关处理两者。
闰秒如何影响 Unix 时间戳?
严格来说,Unix 时间戳忽略闰秒。它们把每天算作正好 86,400 秒。现实世界的 UTC 有偶尔的闰秒(添加以保持原子时间与地球自转一致),但 Unix 时间不包括它们。这意味着 Unix 时间每隔几年就会从 UTC 漂移一小部分秒。
实际上,这对应用代码很少有影响。NTP(网络时间协议)处理这种差异。如果你需要严格的 TAI 或原子时间,Unix 时间戳不是正确的工具。
什么是"ISO 8601"?
ISO 8601 是日期和时间格式的国际标准,旨在无歧义且机器可读。示例:
- `2023-11-14`(仅日期)
- `2023-11-14T22:13:20`(日期和时间,无时区)
- `2023-11-14T22:13:20Z`(UTC,"Z" 代表 "Zulu time")
- `2023-11-14T22:13:20+05:00`(带时区偏移)
- `2023-11-14T22:13:20.123Z`(带毫秒)
- `20231114T221320Z`(紧凑形式,无分隔符)
ISO 8601 是存储和交换日期/时间值的推荐格式,因为它能按字典序排序并能无歧义地解析。大多数 API 都使用它。
如何获取当前 Unix 时间戳?
在所有主要语言中:
```bash # bash date +%s ```
```python import time time.time() # 1700000000.123(浮点数,带小数秒) int(time.time()) # 1700000000(整数秒) ```
```js Date.now() / 1000 // 1700000000.123 Math.floor(Date.now() / 1000) // 1700000000 ```
结论
Unix 时间戳是计算中时间的通用语言。它们是简单的整数,易于比较、存储,且与时区无关。纪元是 1970 年 1 月 1 日,时间戳从那时起按秒计数。
偶尔换算的话,UtilBoxx 时间换算工具 私密、免费、加载后离线可用。批量或脚本工作用 Python 的 `datetime` 或 bash 的 `date` 命令可以处理任何数据量。交互式工作用 JavaScript 的 `Date`,它内置在每个浏览器中。
心算捷径:1,000,000,000 = 2001(Unix 十亿秒),1,500,000,000 = 2017,2,000,000,000 = 2033。有了这些锚点,你可以在脑中估算任何 10 位数时间戳的年份。记住:再过 12 年,2038 问题就会到来,所以现在就审计你的 32 位时间戳。