日期时间格式速查表 - strftime/ISO 8601/时间戳大全

日期 bug 多半是时区 bug——本机看着对的 14:00,换台服务器就差出 8 小时。本表按 strftime 格式符、ISO 8601、时区与偏移、各语言格式化方法、时间戳转换组织,把每个 token 对应到什么输出讲清,并点出 UTC 与本地时区互转的常见坑。写日志格式、定义接口时间戳、解析 ISO 串时常来对照。读完能选到跨服务器、跨端往返一致的日期写法。

参考手册·共 50 条命令·最后更新 2026-07-21
datetime时间格式strftime

典型使用场景

面向所有要在代码里正确表达「时间」的开发者。本表覆盖四类写法:strftime 占位符(%Y/%m/%d 等)、ISO 8601 系列(带 Z、带偏移、带毫秒、周日期、序数日、持续时间)、各语言的标准库格式化写法,以及 Unix 时间戳的取用与互转。真正的难点从来不是「怎么打印」,而是时区语义:同一时刻在 UTC 和本地时区是两个字符串,America/New_York 这类 IANA 标识还含夏令时。表里的 date -d @时间戳、Intl.DateTimeFormat、now + timedelta 这几条能覆盖绝大多数格式化与换算需求。

strftime 格式符 13

%Y
四位年份(2024)
%y
两位年份(24)
%m
月份(01-12)
%d
日期(01-31)
%H
小时 24 小时制(00-23)
%I
小时 12 小时制(01-12)
%M
分钟(00-59)
%S
秒(00-59)
%p
AM/PM 标记
%A
星期全名(Monday)
%B
月份全名(January)
%Z
时区名称(UTC/CST)
%s
Unix 时间戳(秒)

ISO 8601 标准 7

2024-01-15
日期格式(YYYY-MM-DD)
2024-01-15T10:30:00Z
UTC 时间(Z 表示零偏移)
2024-01-15T10:30:00+08:00
带时区偏移
2024-01-15T10:30:00.123Z
带毫秒精度
2024-W03-1
ISO 周日期(第 3 周周一)
2024-015
ISO 序数日(当年第 15 天)
PT1H30M
持续时间(1 小时 30 分)

时区与偏移 6

UTC
协调世界时(基准时区)
GMT
格林威治标准时间(等同 UTC)
+08:00
东八区偏移(北京时间)
Asia/Shanghai
IANA 时区标识
America/New_York
IANA 时区(含夏令时)
DST
夏令时(Daylight Saving Time)

各语言日期格式化 7

new Date().toISOString()
JavaScript ISO 格式
datetime.now().strftime("%Y-%m-%d")
Python strftime 格式化
date("+%Y-%m-%d %H:%M:%S")
Shell date 命令
SimpleDateFormat("yyyy-MM-dd")
Java 格式化(yyyy=年 MM=月)
time.Now().Format("2006-01-02")
Go 格式化(参考时间)
chrono::Local::now()
Rust chrono 库获取本地时间
Intl.DateTimeFormat().format()
JS 国际化日期格式化

时间戳转换 6

Date.now()
JS 获取毫秒时间戳(13 位)
int(time.time())
Python 获取秒级时间戳
date +%s
Shell 获取时间戳
new Date(1705312200 * 1000)
JS 时间戳转日期对象
datetime.fromtimestamp(1705312200)
Python 时间戳转日期
date -d @1705312200
Shell 时间戳转可读日期

日期运算 6

now + timedelta(days=7)
Python 日期加 7 天
new Date(Date.now() + 86400000)
JS 日期加 1 天(毫秒)
date -d "+1 days"
Shell 日期加 1 天
d1 > d2
日期比较(先转同一类型)
(d2 - d1).days
Python 计算日期差值(天数)
dayjs(d1).isAfter(d2)
JS dayjs 日期比较

常见日期格式 5

2024-01-15 10:30:00
SQL/MySQL 默认格式
Mon, 15 Jan 2024 10:30:00 GMT
RFC 2822(邮件/HTTP 头)
2024/01/15
常见斜杠分隔格式
20240115
紧凑日期格式(YYYYMMDD)
1705312200
Unix 时间戳(秒)

参数矩阵

参数作用示例
%Y / %m / %d / %H:%M:%Sstrftime 占位符拼出人类可读日期,是 shell 与 C 系库的标准写法date "+%Y-%m-%d %H:%M:%S"
ISO 8601 带 Z 或偏移机器间传输与存储用带时区信息的 ISO 字符串,跨时区不失真2024-01-15T10:30:00Z
Unix 时间戳秒级整数,唯一表示一个绝对时刻,做差值/排序最省事int(time.time())
时区标识把本地时间与绝对时刻挂钩;IANA 标识自带夏令时规则America/New_York
语言库格式化各语言标准库按同一份时间数据输出不同格式,避免手写格式化Intl.DateTimeFormat().format()
日期算术与比较加减天数与比较先后,先把两边转成同一类型再比now + timedelta(days=7)

易错点与避坑指南

现象同一份日志在服务器和浏览器显示的时间差了几个小时。

原因一边按 UTC 解析、一边按本地时区解析;%Y-%m-%d 这类无时区字符串被当成本地时间。

处置存储统一存 UTC(2024-01-15T10:30:00Z),只在展示层用 toISOString() 或指定 IANA 时区转换。

现象写 "%Y-%m-%d" 生成的时间串被后端解析后日期整体偏移。

原因%Y-%m-%d 是 strftime 写法,ISO 8601 用的是 YYYY-MM-DD;部分后端把前者当字符串硬解析。

处置接口层一律输出 ISO 8601 的大写 T 分隔形式,格式化交给前端或专门的日期库。

现象每年 3 月和 11 月,同一时刻的时间戳对不上预期。

原因时区含夏令时(DST),偏移量随日期变化,固定加 8 小时的做法在换季时会错一小时。

处置用 Asia/Shanghai、America/New_York 这类 IANA 标识交给时区库换算,不要手算偏移。

现象用「加 24 小时」实现「加一天」,夏令时当天结果差一小时。

原因夏令时切换日当天只有 23 或 25 小时,固定毫秒加法与日历语义不一致。

处置按日历语义加一天:Python 用 now + timedelta(days=1),JS 用 new Date(Date.now() + 86400000)。

排障路径

  1. 1把 Unix 时间戳转成可读日期确认时区

    date -d @1705312200

    输出带本机时区的时间,用它和接口返回的字符串逐字段比对。

  2. 2确认同一时刻的 UTC 与本地表示

    date -u "+%Y-%m-%dT%H:%M:%SZ" && date "+%Y-%m-%dT%H:%M:%S%z"

    两条命令并排执行,差值就是本机时区偏移。

  3. 3在 JS 里按指定时区输出日期

    new Intl.DateTimeFormat("en-US",{timeZone:"Asia/Shanghai"}).format(new Date())

    时区名必须是合法 IANA 标识,写错会直接抛 RangeError。

命令示例

把 Unix 时间戳转成 UTC 的可读日期

date -u -d @1705312200 '+%Y-%m-%d %H:%M:%S UTC' date -u -d @1705312200 '+%Y-%m-%dT%H:%M:%SZ'

加 -u 强制按 UTC 解释,否则输出会跟着机器的本地时区变化,排查时区问题时就看不出差异了。

输出

2024-01-15 09:50:00 UTC
2024-01-15T09:50:00Z

同一时刻在三个时区的 ISO 表示

python -c " from datetime import datetime, timezone from zoneinfo import ZoneInfo d = datetime.fromtimestamp(1705312200, tz=timezone.utc) print('utc ', d.isoformat()) print('shanghai ', d.astimezone(ZoneInfo('Asia/Shanghai')).isoformat()) print('new york ', d.astimezone(ZoneInfo('America/New_York')).isoformat()) "

三个串指向同一瞬间,差别只在偏移量。America/New_York 这次显示 -05:00,是因为 1 月处于标准时间而非夏令时。

输出

utc       2024-01-15T09:50:00+00:00
shanghai  2024-01-15T17:50:00+08:00
new york  2024-01-15T04:50:00-05:00

在 JS 里按指定时区输出日期

node -e " const ms = 1705312200000, d = new Date(ms); console.log(d.toISOString()); console.log(new Intl.DateTimeFormat('en-US', { timeZone: 'Asia/Shanghai', dateStyle: 'long', timeStyle: 'short' }).format(d)); console.log(new Intl.DateTimeFormat('en-US', { timeZone: 'America/New_York', dateStyle: 'long', timeStyle: 'short' }).format(d)); "

toISOString() 永远是 UTC,而 Intl.DateTimeFormat 按 timeZone 选项渲染。两者相差 8 小时,恰好是 Asia/Shanghai 的偏移。

输出

2024-01-15T09:50:00.000Z
January 15, 2024 at 5:50 PM
January 15, 2024 at 4:50 AM

算日期差值与加一天

node -e " const d1 = new Date('2024-01-15T00:00:00Z'); const d2 = new Date('2024-03-15T00:00:00Z'); console.log('days', (d2 - d1) / 86400000); const d = new Date('2024-01-15T10:30:00Z'); console.log('plus1day', new Date(d.getTime() + 86400000).toISOString()); "

先转成毫秒数再相减得到的是时长意义上的天数;要按日历加减,用 Python 的 timedelta(days=n) 才是日历语义。

输出

days 60
plus1day 2024-01-16T10:30:00.000Z

常见坑与注意事项

  • 秒级与毫秒级时间戳不要混用:Date.now() 是 13 位,Unix 时间戳是 10 位,差三个数量级会让日期整体偏移。
  • 存储与传输统一用带时区的 ISO 8601(带 Z 或偏移),只在展示层转本地时区,否则服务器与浏览器显示必然不一致。
  • 不要用「加 24 小时」代替「加一天」:夏令时切换当天实际是 23 或 25 小时,日历语义要用日期库的天数运算。
  • %Y-%m-%d 只能用于显示。它没有时区与时间部分,传给按 UTC 解析的服务很容易整体偏移一天。
  • IANA 标识(如 America/New_York)自带夏令时规则,不能用固定偏移量代替,否则每年换季时间都会错一小时。

提示

  • ISO 8601 是国际标准格式,推荐在 API 和数据库中统一使用。
  • Go 的参考时间是 2006-01-02 15:04:05(Mon Jan 2 15:04:05 MST 2006)。
  • Unix 时间戳是秒数(10 位),JavaScript 的 Date.now() 是毫秒数(13 位)。
  • 处理时区问题时,建议统一用 UTC 存储,显示时再转换为本地时区。
  • Java 的 SimpleDateFormat 线程不安全,多线程环境推荐用 DateTimeFormatter。

常见问题

为什么 Date.now() 是 13 位而 Unix 时间戳是 10 位?

因为单位不同。Unix 时间戳以秒为单位,1705312200 就是秒;JavaScript 的 Date.now() 返回毫秒,所以同一个时刻是 1705312200000。两者相差正好三个数量级,混用会让时间落在 1970 年前后或几万年之后,表现为日期整体偏移或直接超出可表示范围。JS 里 Date 构造器接受毫秒,所以从秒级时间戳还原必须先乘 1000。

同一个时刻为什么在服务器和浏览器显示的时间不一样?

因为「本地时间」不是一个绝对时刻。2024-01-15T10:30:00+08:00 与 2024-01-15T02:30:00Z 指向同一瞬间,但前者按各自本地时区渲染就得到不同字符串。要消除差异,存储与传输统一用 UTC(带 Z 或 +00:00),只在最靠近人的那一层转成本地时区。ISO 8601 的带偏移形式(如 +08:00)既保留了绝对时刻,也保留了原始的偏移意图,比裸本地时间更安全。

用「加 24 小时」实现「加一天」,错在哪里?

因为一天不一定是 86400 秒。夏令时切换那天,本地时间的 00:00 到次日 00:00 只有 23 小时(春季前移)或 25 小时(秋季后移),此时用毫秒数相加得到的时间在本地时区下显示会差一小时。要表达日历意义上的「加一天」,应当用日期库的天数运算(Python 的 timedelta(days=1) 就是日历语义),或先把日期部分解析出来再加一天,而不是做时长加法。

%Y-%m-%d 这种写法为什么容易被后端解析偏掉?

因为它没有时区与时间部分。写成 %Y-%m-%d 得到的是「某个时区的某一天」,一旦传给按 UTC 解析的服务,就可能整体偏移一天——东八区生成的 2024-01-15 被当作 UTC 午夜解析,落到美国的用户那里就成了 1 月 14 日。稳妥做法是接口层一律用带时区的完整 ISO 8601 串;只有展示给人看的短日期才用 %Y-%m-%d,并且明确它只是显示格式,不能当作数据存储。

序数日(2024-015)和周日期(2024-W03-1)该怎么用?

两者都是 ISO 8601 里的日历表示,用于需要「一年中的第几天」或「一年中的第几周」的业务。周日期由 ISO week-numbering 规则算出,星期一是每周第一天,含 1 月 4 日的那一周是第 1 周,所以跨年时周数会跳变;序数日则把一年摊成 1 到 366 的连续编号。做报表按周汇总时用周日期最省事,而按天累计的场景用序数日更容易与数组下标对齐。两者都不适合人眼阅读,展示层仍应换成 YYYY-MM-DD。

官方参考来源

下方为命令对应的官方权威文档,供你核对最新用法与深入查阅。

由 巧匠 维护

公开更新于 2026年7月21日,内容持续校对官方文档。

联系我们

命令或描述有误?提交反馈、商务合作或产品建议都可发送邮件给我们。

联系我们