cron 时区陷阱 - 避免定时任务的漂移
以本地时间配置的 cron 任务在夏令时切换期间会静默地重复执行或跳过。本文详解其故障模式,介绍以 UTC 运行调度的方案、Kubernetes CronJob 的 timeZone 字段,以及云调度器如何处理同样的问题。
在 19 世纪末采用标准化时区之前,每座城市都使用自己的地方太阳时。正午被定义为太阳到达天空最高点的时刻,这意味着向东仅 100 公里的城市就会快几分钟。当交通速度缓慢时这套系统运行良好,但铁路的扩张使其陷入混乱。当沿线每个车站都使用略有不同的时钟时,列车时刻表几乎无法协调。
解决方案是将地球分为 24 个经度带,每条带大约跨 15 度经度,代表一小时的时差。桑福德-弗莱明爵士于 1879 年提出了这一方案,到 1884 年华盛顿国际子午线会议确定英国格林尼治为本初子午线(经度 0 度)。现在所有时区都以协调世界时(UTC)为基准定义偏移量,UTC 由格林尼治皇家天文台维护。
UTC 偏移量表示某地标准时间与 UTC 之间相差多少小时(有时包括分钟)。东京使用 UTC+9,即当地时间比 UTC 早 9 小时。纽约在标准时间期间使用 UTC-5,比 UTC 晚 5 小时。当 UTC 为 12:00 时,东京是 21:00,纽约是 07:00。
偏移量的范围从 UTC-12(贝克岛)到 UTC+14(基里巴斯莱恩群岛)。UTC+14 的存在意味着在任何给定时刻,地球上有些地方正同时经历三个不同的日历日期。这种不对称性的存在是因为某些太平洋岛国选择将其工作日与澳大利亚和新西兰的贸易伙伴对齐,而非与国际日期变更线对面地理位置更近的地区对齐。
并非所有时区都遵循整一小时的增量。印度使用 UTC+5:30,与邻国相差 30 分钟。尼泊尔更进一步,使用 UTC+5:45,是全球少数采用 45 分钟偏移的时区之一。伊朗(UTC+3:30)、缅甸(UTC+6:30)和新西兰的查塔姆群岛(UTC+12:45)也使用非整数偏移量。
这些特殊偏移量通常源于政治或地理决策。印度选择 UTC+5:30 作为其东西两端适用时间的折中。尼泊尔选择 UTC+5:45 部分原因是为了与印度区分。对于安排国际通话或会议的人来说,这些非整数时区增加了复杂性,因为简单的心算不再好用。
时区规则的权威来源是 IANA 时区数据库(通常称为 tz 数据库或 zoneinfo)。它为每个地区分配标识符,如“America/New_York”或“Asia/Tokyo”,并编码了 UTC 偏移变更、夏令时转换和政治边界变动的完整历史。每个主流操作系统和编程语言都依赖此数据库进行准确的时间转换。
该数据库每年更新数次,以反映各国政府宣布的时区规则变更。当萨摩亚在 2011 年 12 月 30 日跳过一天,从 UTC-11 变为 UTC+13 时,或当朝鲜在 2015 年将时钟调整了 30 分钟(并在 2018 年撤销了这一变更)时,这些决定都被记录在 tz 数据库中。保持数据库副本更新的软件能自动处理这些转换;过时的系统则会产生错误的转换结果。
理解时区的意义不仅在于知道其他地方现在几点。编写处理时间戳的软件的开发者必须以 UTC 存储时间,仅在显示时才转换为本地时间。旅行者在预订转机航班时需要考虑时区变化。跨国企业必须找出重叠的工作时间以便进行同步沟通。
世界时钟工具可以免除这些换算中的心算负担。你无需记忆偏移量并考虑夏令时变化,只需一眼就能看到任何城市的当前时间。这在夏令时转换前后的几周尤其有价值,因为在此期间两个城市之间的偏移量会临时变化一小时,常常让人措手不及。
这篇文章对您有帮助吗?
以本地时间配置的 cron 任务在夏令时切换期间会静默地重复执行或跳过。本文详解其故障模式,介绍以 UTC 运行调度的方案、Kubernetes CronJob 的 timeZone 字段,以及云调度器如何处理同样的问题。
子午线是定义经度并支撑全球时区体系的南北向基准线。本文介绍子午线的本质、格林尼治如何成为本初子午线、子午线与时间的关系,以及历史标线与现代GPS之间102米的偏差。
新年以一波26小时的浪潮降临全球,从基里巴斯的莱恩群岛开始,到贝克岛结束。本文追踪这一浪潮经过各大城市的足迹,介绍仍在庆祝的非公历新年,并探讨新年对运行在UTC上的IT系统意味着什么。