无需上传, 100% 本地处理, 无需账户

文章

ISO 8601时长:P1DT2H是什么意思

YouTube API的响应里,某个视频的时长写作PT4M13S。日历邀请里带着P15DT5H0M20S这样的值。某个目录服务器给账户打上20260424174227.0Z这样的时间戳,看起来和前面那些有关联,实际上却完全是另一回事。这些简洁的字符串遵循着值得了解的规则,因为读错就会把分钟变成月份。这篇文章带你梳理ISO 8601时长格式:每个字母代表什么、这种格式出现在哪里,以及最需要留意的一点:按这种方式写出的时长并不总是固定不变的时间量。

P、T,以及每个字母的含义

ISO 8601时长以P(period)开头。接下来是日期部分的各个成分,每个都是数字加上单位字母:Y表示年,M表示月,W表示周,D表示日。T用来分隔日期部分和时间部分:H表示小时,M表示分钟,S表示秒。每个成分都是可选的,只写需要的部分即可。PT15M是15分钟,P1DT2H是1天2小时,P3W是3周。T不是可有可无的装饰:M在T之前表示月,在T之后表示分钟,所以P1M是1个月,而PT1M是1分钟。最后出现的那个成分可以带小数,比如PT0.5S表示半秒。而且各个单位不会自动进位:PT90M是表示一个半小时的完全有效写法。

ISO 8601时长P3Y6M4DT12H30M5S的结构:P表示时长的开始,Y M D是日期单位,T切换到时间部分,H M S是时间单位

你实际会在哪里遇到这种格式

这种语法几乎无处不在,只是不太引人注意。YouTube Data API把每段视频的时长都报告为ISO 8601时长(PT4M13S)。HTML在time元素的datetime属性里接受时长写法。日历邀请也在用它:iCalendar标准(RFC 5545)把活动时长写成PT1H0M0S这样的形式,不过它的语法里去掉了年和月。XML Schema的xs:duration覆盖了完整形式,甚至允许在前面加负号来表示负时长。标准库可以直接解析它:java.time用Period.parse和Duration.parse来读取P和T字符串,很多其他语言里也有类似的划分。如果你要生成机器可读的排期、订阅源或API,这种格式就是表达“多长时间”的通用语言。

为什么P1M不是固定的秒数

PT15M永远是900秒。P1M不是:一个月是28天、29天、30天还是31天,取决于它从哪天开始,所以P1M只有绑定到具体日期之后才会变成一个确定的值。就连P1D也不能保证是24小时。在欧盟,2026年3月29日星期日会拨快时钟,所以那一天在日历上只有23小时:在同一个周六晚上分别加上P1D(一个日历日)和加上PT24H(整整24小时),会落到不同的时刻上。这正是java.time要区分Period(日历单位)和Duration(精确秒数)两种类型的原因,也是日期库在转换时长之前要先要求一个参考日期的原因。请把Y、M、W、D这几个成分当作日历运算来处理,只有H、M、S才是固定不变的时间量。

不是时长:20260424174227.0Z

像20260424174227.0Z这样的字符串看起来可能属于同一个家族,但它其实是一个时间戳,而不是时长,也不属于ISO 8601。它是GeneralizedTime,来自ASN.1的一种格式,是LDAP目录和X.509证书使用的记法。可以把它当成固定宽度的字段来读:年份2026,月份04,日期24,接着是17:42:27,一个可选的小数部分(.0),以及表示UTC的Z。你会在Active Directory的whenCreated和whenChanged等属性、LDAP导出结果,以及证书内部见到它,RFC 5280要求2050年及以后的有效期日期使用GeneralizedTime。区分它和ISO 8601简洁形式的关键线索是缺少T:如果是ISO写法,同一个时刻会写成20260424T174227Z。

GeneralizedTime字符串20260424174227.0Z逐字段解码为2026年4月24日17:42:27 UTC

不看规范也能读懂

如果只是要解读一个字符串,我们的ISO时长转换器可以把任意P/T时长解析成各个成分以及总秒数,也可以根据你输入的数字反向拼出字符串。如果你手头的不是时长字符串,而是两个具体的时刻(比如一个从22:00到06:30的班次),时间段计算器能算出经过的时间,包括跨越午夜的情况。这两个工具都完全在你的浏览器里运行:你输入的内容不会离开你的设备。如果不借助工具也想快速读懂,记住两个诀窍就能应付大多数情况:先找T,判断M是月还是分钟;记住T左边的一切都是日历运算,而不是固定的秒数。

本文涉及的工具

常见问题

PT1M和P1M是一回事吗?

不是。字母M在T这个分隔符两侧含义不同:P1M是1个月,PT1M是1分钟。这是这种格式里最常见的误读,也曾因此导致API出现过上线的漏洞。拿不准的时候,先找T:T之前的一切按年、月、周、日计数;T之后的一切按小时、分钟、秒计数。一个格式正确的时长,不会在T之前出现时间单位,也不会在T之后出现日期单位。

90分钟怎么写成ISO 8601时长?

PT90M和PT1H30M都是合法的写法,表示的是同一段时间。ISO 8601不要求各个成分落在常规范围内,所以分钟数超过59或小时数超过23都没问题。解析器两种写法都能接受;至于系统会输出哪一种,取决于它是否做了归一化处理。如果你生成的时长是给人读的,PT1H30M更友好;如果你在代码里比较时长,应该比较总秒数而不是字符串本身,正因为两个不同的字符串可能表示同一件事。

时长和区间有什么区别?

时长只说明有多长,不涉及日历上的具体位置:P3D是3天,从哪天开始都可以。ISO 8601的区间会用斜杠把时长绑定到实际日期上:2026-07-04T00:00:00Z/P3D表示从2026年7月4日开始的3天,而像2026-07-04/2026-07-07这样的起止日期对表达的是同一段区间。还有带R前缀的重复区间:R5/2026-07-04T00:00:00Z/P1D表示从那个起始时刻开始,每天重复5次。区间解决了日历单位的歧义,因为绑定到具体日期之后,P1M总是有一个确定的长度。

来源