news 2026/10/24 5:08:02

时区划分的底层逻辑:从UTC、夏令时到跨时区协作与编程实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
时区划分的底层逻辑:从UTC、夏令时到跨时区协作与编程实践

先说一个我踩过的坑。有一回我和纽约的同事约线上会议,我这边写的是北京时间下午3点,他那边日历自动把它显示成了纽约时间下午3点。到了约定时间,我等了整整一小时,人始终没上线——人家那边是凌晨2点,换谁也不会来开会。这事过后,我认真把世界时区划分从头到尾捋了一遍,才发现从“当地时间”到“UTC+8”这一串东西背后,全是火车时刻表、原子钟、夏令时和各国政府拍板的故事。

这篇文章不打算写成百科词条。我真正想讲的,是三层东西:第一,时区是怎么被发明出来的,底层逻辑到底是什么;第二,为什么真实地图上的时区线弯弯曲曲,一点也不像教科书上画的整齐经线;第三,我们这些普通人、旅行者和写代码的人,在算时差、做排期、跨洋开会时,到底会遇到哪些坑,又该怎么应对。如果你经常跨国开会、出差,或者在系统里处理过其他地区的时间,这篇文章应该能给你省下不少白等的时间和半夜爬起来改问题的精力。

1. 从“一城一个时间”到“全球24小时刻度”:时区是怎么被发明的

1.1 铁路出现之前,每个地方都有自己的“太阳时间”

在机械钟表和铁路时代之前,所谓“几点”其实是太阳的投影。古人对时的标准很简单:太阳升到头顶最高点,就是正午12点。但地球是一个球体,不同经度的地方看到太阳到达最高点的时刻必然不同。经度差1度,正午就差4分钟,差15度,就差整整1小时。北京和西安的经度差大约7度,两地的正午就相差接近半小时。在马车和步行的年代,这个误差无人在意,每个城镇各过各的“当地时间”就好。

真正让情况失控的是铁路。19世纪中期,火车把一个个城市连起来,列车时刻表成了灾难:一个站的“9点”和另一个站的“9点”不是同一个时刻,调度员面对满墙时刻表,得先做一堆加减法才能知道哪趟车先开。与此同时,电报也要求收发双方在时间上对齐,否则无法确定报文先后。英国铁路公司最早受不了这种混乱,开始统一采用伦敦格林尼治天文台的平太阳时,也就是后来被称作 GMT 的那个东西。

这个“铁路带来的统一时间”看似只是交通行业的内部整顿,却是全世界后来确立标准时间的第一步。时区不是天文学家坐在办公室里拍脑袋想出来的,它完全是被交通和通信逼出来的。

1.2 1884年那次国际会议,定下了“15度一小时”的规矩

铁路统一时间只能在局部奏效,全球规模的贸易和航海还需要一个共同的基准。19世纪的航海家要确定自己的经度,靠的是精确的天文钟和已知位置的“港口时间”,而当时几乎所有海图和天文年历都以英国格林尼治为基准。换句话说,格林尼治已经在事实上成了全球海洋的时间原点,只差一个国际会议来盖章确认。

1884年,国际子午线会议在美国华盛顿召开,会议做出了几个影响至今的决定:

  • 以通过格林尼治天文台旧址的经线作为本初子午线,也就是经度0度;
  • 把地球表面按经度划分为24个时区,每个时区跨15度,相邻时区相差1小时;
  • 大致以180度经线附近作为国际日期变更线,作为新一天的起点。

为什么是15度一小时?道理很简单:地球24小时自转一圈360度,360除以24等于15。把这个数字套到地球上,就是沿经度切出24块西瓜:每块瓜对应一个标准时区,东边的瓜比西边的瓜早看到太阳,所以东边的时间更“早”。

需要注意,这套模型在当时是惊人的进步,但它只是理论框架。它假设所有时区边界都是笔直的经线,可真实世界立刻用各国疆界、岛屿归属和经济往来给这套整齐的切分法打了补丁。这就是下一部分要讲的事:真地图上的时区,到底有多不守规矩。

2. 真实世界里的时区边界:为什么地图上的线弯弯曲曲

2.1 行政区划、经济联系与“不想和邻居差一小时”的算计

如果真按15度经线一刀切,很多国家会被劈成两半:东边早上9点,西边刚过8点,同一个国家内部的火车、电话、电视节目全乱套。所以实际时区的划分几乎完全跟着主权国家走:一个国内部统一用一个或少数几个标准时,边界贴着国界、省界或者河流岛屿拐来拐去。

几个典型例子:

  • 中国的地理经度从东经73度左右一直延伸到东经135度左右,理论上跨越约5个时区,但全国统一采用东八区时间(北京时间)。这也造成了很有意思的现象:东部沿海早上8点上班时太阳已经很高,而在西部很多地方,早上8点天可能才刚刚亮。全国用同一套表,生活节奏却差别很大。
  • 俄罗斯从欧洲部分到勘察加半岛,东西跨度约170度经度,被划分为11个时区,从UTC+2一直排到UTC+12。
  • 法国本土面积不大,但加上遍布太平洋、大西洋、印度洋的海外属地,实际覆盖大约12个时区,比俄罗斯还多。
  • 很多国家嫌“一小时”的步长太粗,干脆采用半时区。印度用UTC+5:30,尼泊尔用UTC+5:45,前者让全国只用一个时间,后者连15分钟都要凑个整数,旅行者第一次看到这类偏移量通常都会愣一下。

我对这类“政治时区”的体会是:时区本质上是“时间政治”,不是“时间物理学”。一个地区用哪个时区,往往是交通、贸易、行政效率综合博弈的结果,而不是在地图上拿尺子量出来的。

2.2 国际日期变更线:为了“日期连续”,人类强行把线掰弯了

180度经线在理论上应该是全球日期的“换班点”:跨过它,日历就要跳一天。但太平洋上有太多有人居住的群岛,如果严格按经线走,同一个群岛可能在今天和明天之间被劈开,这显然没法生活。所以国际日期变更线被画得歪歪扭扭,绕开了一个又一个岛礁。

最典型的例子是基里巴斯。这个国家横跨多个经度,如果日界线严格沿180度走,国土会被切成两个日期,连内部做生意都要先问一句“你那边的今天是几号”。后来它干脆把实际时区定成了UTC+14,让整个国家统一在日界线西侧。这样一来,基里巴斯不但解决了内部日期不一致的问题,还意外成为地球上最早迎来新年的地方。

另一个著名案例是萨摩亚。它原本位于日界线东侧,时区是UTC-11,和澳大利亚、新西兰做生意时,双方总有一个在工作日、另一个在周末,能共事的时间窗口少得可怜。2011年,它决定把时区调到日界线西侧(标准时间UTC+13),于是12月29日过完午夜之后,直接跳到了12月31日——12月30日这个日期在萨摩亚永远消失了。

由此出现一个罕见的奇观:萨摩亚和美属萨摩亚距离很近,坐小飞机半小时就能到,但两者之间横着整整一天。你在前者看“明天”,到了后者却回到“昨天”。人类用行政力量让“时间”在物理上发生了跳跃,这是时区划分最反直觉、也最迷人的地方。

3. 算时差前必须搞懂的三组概念:GMT、UTC与夏令时

3.1 GMT是“看天”的旧标准,UTC是“数原子”的现代基准

前文反复出现GMT,它诞生时和航海、铁路深度绑定,是格林尼治的平太阳时。但地球自转并不是匀速的,用“太阳走到头顶”来定义一秒,在现代精密测量面前不够稳定。1972年起,国际社会改用UTC(协调世界时)作为全球统一的时间基准。UTC由全球多台原子钟加权算出来,必要时用闰秒做微调,让它跟地球自转之间不至于偏离太多。

说人话:GMT是靠观测天体获得的时间,UTC是靠数原子振动获得的时间。两者之间的差异通常在亚秒级,普通人日常算时差完全可以不区分,但在代码、日志、金融交易这些对时间敏感的场合,必须明确使用UTC。

一个更容易被忽略的点是:UTC自带一个“零刻度”的含义,就像全世界钟表的零点。北京时间是UTC+8,意思是当UTC是0点时,北京已经是早上8点;纽约冬令时是UTC-5,意思是当UTC是0点时,纽约还是前一天晚上19点。谁在UTC刻度上数字更大,谁的本地钟面就更“早”。

3.2 夏令时:一年要拨两次钟的“人为时间”

夏令时(DST)的思路是:夏季天亮得早,把表往前拨一个小时,让原本属于早晨的太阳光被“挪到”傍晚,人们下班后还亮着,能省下一笔照明能源。一百多年前欧洲国家最早推行这个制度,后来逐步传播,今天全球大约有70个国家和地区仍在实行。

北半球的典型节奏是3月底到10月底:以伦敦为例,冬季用UTC+0,夏季用UTC+1;纽约冬季是UTC-5,夏季是UTC-4。南半球正好相反,悉尼的夏令时从10月到次年4月。中国在1986年到1991年之间也试行过夏令时,后来取消;所以北京时间的UTC偏移全年恒定为UTC+8,没有“夏季版”。

这个制度对记时差的人来说是最大的暗坑。很多人的直觉记忆是“纽约比北京慢13小时”,但纽约一年里有约7个月实际只慢12小时。每年3月和11月切换的那两周,是全球会议约错率最高的时段。我有个同事就曾因为在3月第二个周日忘了调夏令时,让整个团队在会议室空等了半小时。

为了直观对照,我整理了一张常用地区时差表(以北京时间为基准):

地点标准时间夏令时与北京时差(冬/夏)
北京UTC+8不实行0
东京UTC+9不实行比北京早1小时
伦敦UTC+0UTC+1慢8小时 / 慢7小时
纽约UTC-5UTC-4慢13小时 / 慢12小时

提示:跟任何人约跨时区会议,都要连日期一起说清楚“你指的是哪个区间的时差”。尤其南半球的夏令时和北半球正好错开半年,光说“夏令时”远远不够。

3.3 遇到“UTC+5:45”这种怪时间,怎么快速心算时差

心算时差其实就一步:把两边的时间先换算到UTC,再相减。举例:北京下午3点,想知道纽约几点。北京是UTC+8,所以15:00减去8小时得到UTC 07:00;纽约冬令时是UTC-5,07:00再减5小时,得到02:00,也就是纽约凌晨2点。

更快的口算法是直接用偏移量做差:UTC+8和UTC-5之间相隔13个小时。只是要特别注意“东早西晚”这件事:UTC偏移量大的地区太阳先升起,时间数字更大。所以北京比纽约“早13个小时”,而不是“晚13个小时”。很多人把这两个字说反了,约会议时就会出现“我说早,他理解成晚”的乌龙。

遇到印度的UTC+5:30也一样:UTC+8减5:30等于2.5小时,北京是下午3点时,印度是中午12点半。尼泊尔的UTC+5:45就更考验耐心——差值是2小时15分钟。真要在这种地方做生意,建议别心算,直接在手机里加一个“世界时钟”小组件,一屏全解决。

4. 程序员的时区噩梦:差一小时背后藏着多少坑

4.1 为什么不能只信“数值偏移量”,而要认“时区名”

很多初学开发的同行习惯在代码里写:用户设置了一个“09:00”,我给他存成“+08:00”。平时没问题,但一旦涉及跨年、跨国、历史数据,这种写法就是定时炸弹。原因有三:

  • 时区规则会变。某个国家可能突然宣布取消夏令时、或永久启用夏令时,旧偏移量无法表达这种制度变化。
  • 历史规则五花八门。以中国为例,1986年至1991年之间曾试行夏令时,如果你要处理那几年的日志,用“Asia/Shanghai”这个带城市名的时区标识,系统能自动把那几年里7月的时间加1小时;可你要是把偏移量写死成“+08:00”,这些历史数据一定会错。
  • 行政区划也可能调整,同一个城市可能从某个时区切到另一个时区。

所以现代工程的标准答案是:存储和传输统一用UTC,展示给用户时再转换成本地时间;而“本地时间”不能靠裸的偏移量表达,必须用“Asia/Shanghai”“America/New_York”这种语义化时区名。这些名字由IANA维护的时区数据库(tzdata)管理,你可以把它理解成一本收录了全世界时区规则的“字典”:每个时区名对应着所在地的UTC偏移规则、夏令时规则,以及所有历史变更。操作系统、编程语言、数据库全都靠这本字典才能算对“某个时刻在这个地方到底是几点”。

4.2 一条正确的处理链路:存储UTC,展示时再转本地

我平时处理时间数据,坚持三条原则:

  1. 数据库字段统一存UTC的datetime类型或Unix时间戳,不做任何偏移折算;
  2. 在API边界做时区转换,凡是需要给人看的字符串,必须带时区标识或明确的UTC偏移量;
  3. 展示层用前端本地时区,或者按照用户自己设置的时区来渲染,绝不在服务端写死“所有人都看北京时间”。

下面用Python演示一下标准做法:

from datetime import datetime, timezone from zoneinfo import ZoneInfo now_utc = datetime.now(timezone.utc) print("UTC 时间:", now_utc.isoformat()) bj = now_utc.astimezone(ZoneInfo("Asia/Shanghai")) ny = now_utc.astimezone(ZoneInfo("America/New_York")) print("北京时间:", bj.strftime("%Y-%m-%d %H:%M:%S %Z")) print("纽约时间:", ny.strftime("%Y-%m-%d %H:%M:%S %Z"))

JavaScript里用内置的Intl API也能做到同样的事:

const fmt = new Intl.DateTimeFormat("zh-CN", { timeZone: "America/New_York", year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false }); console.log(fmt.format(new Date()));

你只需要把UTC基准的时刻交给语言库,剩下的夏令时、历史变更、半时区规则,全部由底层的时区数据库自动处理。这段代码看起来简单,但它解决的问题一点都不简单。

4.3 日志、定时任务和历史数据里最容易踩的坑

日志分析:如果服务器日志只存“2025-06-01 09:00:00+08:00”,而服务器后来换到了别的时区,或者要和美国机房的对账系统比对,就会乱七八糟。正确做法是日志统一打UTC的ISO 8601格式,例如“2025-06-01T01:00:00Z”,末尾那个Z就是“UTC”的意思。需要给用户看的本地时间,再单独转换一次。

定时任务:在Cron里写“每天9点”却不说清楚9点属于哪个时区,简直是在给自己埋地雷。服务器换了环境、项目换了机房,任务就会莫名其妙地提前或延后一小时。排期配置里应该显式指定时区,比如用TZ=Asia/Shanghai这样的环境变量,把整个服务的“逻辑时区”钉死。

历史数据:如果你在处理1970年之前或2038年之后的日期,别用32位整数做时间戳,否则会撞上“2038年问题”。另一个容易被忽略的是闰秒:UTC每隔一段时间会加一个闰秒来校准地球自转,普通业务不必关心,但金融、航天、高频交易这种对时间精度极其敏感的领域,必须知道它的存在。

我个人的原则是:凡是能存“绝对时刻”的就绝不存“带有模糊规则的本地字符串”。事后想从本地时间倒推绝对时刻,往往会因为夏令时或时区规则变更而失败;而存了UTC时间戳,任何时候都能可靠地还原出任意时区的钟面时间。

5. 跨时区协作与倒时差:我这些年踩出来的实操经验

5.1 邀约跨时区会议,说清时间的“三件套”是什么

远距离协作最大的误会来源,就是只说“9点”,不说“哪里的9点”。我自己现在有个固化的习惯,任何跨时区邀约都写三件套:日期完整写,比如2025-06-10,不写“周二”这种容易被日历弄错的简称;时区名写清楚,北京时间(UTC+8),宁可重复也不要含糊;关键城市都标注,如果参会者在纽约,我会顺手补一句“纽约当地时间为2025-06-09 21:00”。

如果日历系统支持双时区显示,就同时打开“当前时区+对方时区”两个面板;如果不支持,就先用在线世界时钟网站核对一遍再发出去。多花十秒钟核对,能避免让五个人在会议室白等一小时。

还有一个教训:别默认“周一早上”适合所有人。你在北京周一下午4点开会,对应的可能是纽约周一凌晨3点、悉尼周二早上7点。跨时区排会,优先选大家都不是“深夜或凌晨”的时间窗口,并提前问清楚对方国家和地区现在是不是假期。

5.2 向东飞和向西飞,倒时差的策略完全不同

坐洲际航班倒时差,向东飞(比如从北京到纽约,时差约13小时)最难,向西飞(比如北京到伦敦,时差约7到8小时)相对轻松。原因在于,让生物钟“往后拨”比“往前拨”更符合人体自然节律。

向东飞的实操建议:出发前3天开始提前作息,每天把睡觉时间往前挪半小时,让身体先适应“更早的太阳”;飞行途中按目的地时间进食和休息,机舱灯光昏暗时尽量睡,哪怕睡不着也闭眼养神;落地后立刻按当地时间生活,白天多到户外接触自然光,光照是校正生物钟最强的信号。凌晨醒来的话,尽量不要开强光看手机,熬到天亮再起来。

向西飞的策略正好相反:出发前尽量别熬夜,落地后是当地下午或傍晚,撑到当地时间22点再睡,第二天基本就恢复正常了。

补水永远是倒时差的基础:飞行中少喝咖啡和酒精,多喝水。机上吃太油太咸的东西,落地后会加重疲惫感。说实话,我试过各种“科学倒时差法”,最后发现最有效的反而是“别太把时差当回事”——紧张焦虑带来的失眠,往往比时差本身更难对付。

5.3 手机、电脑、手表:设备时区怎么设置最省心

手机:开启“自动确定时区”选项,飞行落地后会自动跳到当地时间。不过要注意,落地瞬间时间突跳,很容易让人误以为“一觉睡过了好几个小时”,所以建议飞机落地后再开机。

电脑:系统的时区设置为“跟随网络”或“自动”,不要手动锁死某个时区,否则出差时日历邀请的换算全会错。会议室预订和邮件客户端的“当前时区”设置也要保持一致。

手表:如果没有GPS自动同步,跨国后直接把它调到目的地时间。很多人喜欢保留“家里时间”的双表盘,我建议如果保留,也要同时显示两个时区的城市名,否则总有一天会看错表盘。

6. 世界时区的冷知识:那些反直觉的“时间特例”

6.1 全球最早迎接新年的地方,不是最“东”的国家

很多人直觉认为最早迎接新年的应该是日本这类极东国家,实际上这个头衔属于太平洋岛国基里巴斯的部分岛屿。基里巴斯的一部分采用UTC+14,当别的地方还在12月31日的下午,它已经跨进1月1日的凌晨。而最晚迎来新年的有人居住地区,是美属萨摩亚等采用UTC-11的岛屿。同一瞬间,地球上可以同时存在两个不同的日期,这也让“跨年直播”在最极端时差下会出现完全相反的景象。

6.2 半小时航程,跨过整整一天

萨摩亚和美属萨摩亚之间,就是上面说的“最极端时差邻居”。两地相距不远,坐小飞机半小时左右,却因为一个在日界线西侧(UTC+13)、一个在东侧(UTC-11),相差整整24小时。前者的周一下午,是后者的周日下午;如果你在萨摩亚的周一出发去美属萨摩亚,落地后你会回到“周日”。跨境快递、船期、合同日期,在这些岛之间的往来账户上经常出现“日期倒退一天”的荒诞戏码。

6.3 时区最多的国家和那些“差45分钟”的怪时间

论覆盖时区数量,法国凭借散布全球的海外属地,大约有12个时区,比俄罗斯的11个还多;美国加上本土和海外领地,也有大约9个时区。时差还常常不是整小时:印度用UTC+5:30,尼泊尔用UTC+5:45,澳大利亚的官方时区也包含一个“澳大利亚中部时间”UTC+9:30。这种半时区通常是一个国家不想再分成两个标准时区,又想让东西部都能对上日常作息,才折中选出的结果。对旅行者来说,这种地方就是“计算器友好度负分”,但对当地居民来说,它的合理性足够强。

为什么有些国家干脆不用夏令时?日本就是一个典型例子,它曾短暂试行过夏令时,后来长期不采用;冰岛虽然地处高纬度,夏季白天极长,也常年固定在UTC+0。说到底,夏令时是节能政策,不是天文规律,用不用完全取决于各国对日照条件和经济成本的判断。

6.4 极地、船舶和空中的“无时区”世界

在南极的科考站,时区更多是“后勤设置”——为了便于和补给基地所在国联系,很多科考站干脆采用补给基地的时区。远洋船舶也一样,有自己的“船时”,通常跟着补给港走。国际航班机组则完全活在UTC里,他们口中的“Zulu时间”就是UTC,签派、航路、进场全部用Zulu对齐,只有落地后的旅客活动才切到当地时间。这些场景里,时区划分早就不是“按经度切西瓜”,而是纯粹的操作工具:哪个时间能让协作不出错,就用哪个。

写到这里,我忍不住回想自己最开始对时区的理解,就是一张写着“0到+12、0到-12”的表格,当时觉得背下来就万事大吉。真正打交道久了才明白,时区本质上是一套人类制定的规则,用来把太阳的位置翻译成彼此能对齐的钟表时间,而且这套规则一直在被生活、经济和行政决定修改着。我现在的基本功就三条:凡是跨时区约定,一定把时间写成“日期+时区名+UTC偏移量”三件套;凡是代码里的时间,一律UTC存储;凡是订机票或开会,先在手机世界时钟里核对一遍。这三条习惯帮我少白等了不少会议,也少改了不少时区引发的线上问题。

如果你也常被时差折磨,不妨从今天起把手机桌面加一个世界时钟小组件,同时看看纽约、伦敦、悉尼和你自己现在分别是几点。看久了,你对“世界时区划分”的直觉会变得很准,也会真正理解:地球不是按一排整齐的经线转的,而是按人类约定好的时间规则在转。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/24 5:07:44

STC芯片命名规则全解析:从丝印到选型避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 5:05:35

MATLAB航空航天工具箱R2023b核心用法:坐标系、DATCOM与卫星场景

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 5:05:31

tftpd64 实战指南:TFTP 协议原理、服务端配置与排错技巧

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 5:05:26

分辨率真相:不是像素越多越清晰,而是全链路匹配

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 5:05:26

AIS船舶追踪系统实战:从数据接入到全球可视化看板搭建

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 5:05:23

C++小学组初赛真题解析:变量、循环与算法入门要点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华