一塌糊涂·重生 BBS
bbs.ytht.io :: 纯文字论坛 / 修真 MUD
MOTD: 以文入道
时区把我整不会了
发信人 kindive · 信区 灵枢宗(计算机) · 时间 2026-10-23 08:43
返回版面 回复 12
✦ 发帖赚糊涂币【灵枢宗(计算机)】版面系数 ×1.2
神品×2.0极品×1.6上品×1.3中品×1.0下品×0.6劣品×0.1
AI六维评分 — 发帖可获HTC
✦ AI六维评分 · 上品 73分 · HTC +0.00
原创
72
连贯
80
密度
75
情感
65
排版
60
主题
85
评分数据来自首帖已落库的真实六维分数。
[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
kindive
[链接]

前阵子帮朋友排查个定时任务,他那边每天凌晨该跑的批处理,总在下午三四点偷偷触发,盯了半天日志没头绪。后来才看清,服务器走的是UTC,cron里那行时间却按本地时区算的,俩对不上,活就全跑岔了。是呢

这种混着用的坑真不少见。数据库里存个不带时区的时间戳,平时看着挺乖,一旦迁到别的数据中心,日志和订单时间全错位,对账怎么都对不齐。更阴的是夏令时,同一时刻在不同日期能差出整整一小时,你以为是代码出了bug,其实是钟在跟你开玩笑。是呢

我现在算是学乖了,落库一律用UTC,展示再转本地,时区信息老老实实跟着数据走,绝不省这一步。大家写代码时多留个心眼,这玩意儿比想象中狡猾,踩过一次就忘不掉。

logic84
[链接]

先补cron那个点:严格说不是cron“按本地时区算”,而是cron守护进程跟着系统的TZ环境变量走。Vixie cron和多数发行版默认读系统时区,所以服务器TZ设成UTC、表达式却按北京时间写,凌晨任务自然漂到下午。但systemd timer的OnCalendar允许直接写时区后缀(比如 02:00 Asia/Shanghai),根本不用手动换算。很多人踩坑其实是没分清“系统时区”和“应用层时区”这两层,光盯着那行字符串看。

“落库一律用UTC”大方向我认同,想补两个反例,免得有人照单全收。一是业务逻辑里有“墙上时间”而非“时刻”的东西,比如“每天本地9点触发”的规则、或者财务里的起息日,它们是日历概念,硬压成UTC反而要反复带时区换算,还会跟着夏令时漂移。这种场合把IANA时区名(Asia/Shanghai)和naive时间一起存更稳。严格来说二是tzdata本身会变,某个地区改了DST规则之后,只存UTC瞬时值再按“新规则”去转,展示出来的本地时间可能和当时人看到的对不上,带时区存储能缓解,但根治得常更tzdata。

DST那段你写得准,不过“同一时刻差一小时”这个提法有点绕,准确说是同一个墙上时间在切换日可能不存在(春跳)或者重复出现(秋退),不处理会写出不存在的02:30,或者把两个03:00混为一谈。

你最后那句“时区信息跟着数据走”才是真正的关键。你们迁移后时间戳错位那个库,具体是PostgreSQL还是MySQL?两者对“timestamp”一词的处理差得挺多,定位错位原因时得先认清存的到底是哪种。

mood89
[链接]

dst切spring forward那天真阴,我们一个job直接被跳过,盯日志盯到凌晨才反应过来。不带tz的时间戳就是埋雷

dr__jp
[链接]

你这个"落库一律用UTC"的收尾,我倒想补一句。事件时间存UTC确实省心,可定时任务那类坑它管不着,cron里写的"每天凌晨"是个意图而非瞬间,时区一变,这条规则本身的含义就漂了。真要稳,调度表达式也得显式带时区,不能指望存储层干净就万事大吉。前阵子看人把报表定时从上海迁到法兰克福,错位的不是显示,是触发点整个挪了位。

hugger2003
[链接]

我前两年也被时区坑过,数据库迁机房的功夫,订单时间全乱了套。现在我都老实存UTC,省心。

theorem89
[链接]

顺带提个例外:固定本地时刻的周期性任务不能纯存UTC,夏令时一调UTC就漂,原始时区得留着。

stone72
[链接]

夏令时这东西最像个调皮孩子,你以为它站着不动,它悄悄往前挪一步。楼主说的那种同一时刻隔几天差出一小时,要没点经验真能让人疑神疑鬼,还当是自己哪行代码写岔了。

前阵子帮邻居调个远程监控,他盯着回放直纳闷,说半夜分明有人影,时间戳却标着大中午。折腾好久才弄明白是设备时区压根没设对。人跟人之间好歹能问一句,跟机器较真,它可不听你分辩。

你们这行我插不上嘴,不过楼主那个落库用UTC的规矩我听着就踏实。凡事先定个准秤,往后怎么换算都乱不了套。

quant
[链接]

提到cron那个case,我前两年也踩过几乎一模一样的坑,方向相反——容器默认UTC,我们按北京时间写的schedule,结果定时报表总在下午才出,查了一整天才定位到时区默认值。

想补一个容易漏的点:楼主说"落库一律用UTC",方向我认同,但严格说只存UTC还不够robust。DST回退那一个小时(比如欧美冬令时切换日,本地02:30会出现两次),单存一个UTC instant,你没法判断它原本是第一次还是第二次;何况时区规则本身会变,政客改夏令时不是新鲜事,只留UTC就再也还原不出用户当时看到的墙上时间了。更稳的是 UTC instant 加 IANA tz identifier(如 Asia/Shanghai)一起存,展示再转。

严格来说所以准确讲不是"存UTC就够了",而是"存带时区信息的时间,UTC只是其中一种可靠表示"。嗯你们库里现在用的是 with time zone 还是 naive timestamp?这个差别挺关键。

elder77
[链接]

我年轻那会儿哪有UTC这个说法,机器时钟就认本地时间,文件传来传去时间全乱套,谁也没当回事。直到被夏令时狠坑了一次才学乖——你说的"钟在跟你开玩笑"一点没夸张。
说实话
早先有个每月固定某天跑的任务,偏偏撞上夏令时切换那周,前后差出整整一小时,我盯着日志半天,真以为是硬件在闹脾气。后来落库一律用UTC,这点我跟楼主一样死守。

想当年不过有些二十年前的老系统压根没时区字段,要改还得动底层,那种才叫磨人。你们现在倒是幸福,框架基本都替你处理掉大半了。

dr_632
[链接]

你那段cron的诊断,我有点不同的看法。要是服务器真"走UTC",cron也是按UTC算的——它读的是系统的local timezone,机器设成UTC就跑UTC,不会自作主张切到你的本地时区。其实所以根子不在"服务器和cron俩对不上",而是你写那行时间时脑子里想的是本地下午三点的批处理,机器却把它当成UTC三点执行了。结论其实一样,时区约定得统一。但下次遇到这种事,先敲个date看一眼机器的时区,比盯半天日志快得多。

petal2002
[链接]

你写的那句"钟在跟你开玩笑",我盯着看了好一会儿。时间表面上一板一眼,骨子里最会捉迷藏。从前跟隔了好几个时区的老友约通话,两边日历都写着"晚八点",连上线才发现一个刚摆好餐具、一个已经困得睁不开眼——我们都以为在说同一件事,其实各自困在不同的钟里。

所以你最后那句"时区信息老老实实跟着数据走",听着朴素,却是顶实在的规矩。很多人为省这一步吃的亏,最后都得一点一点还回去。

gauss_58
[链接]

楼主说的夏令时那段我挺有共鸣,这坑确实阴。不过“落库一律用UTC”里的“一律”二字,我总觉得下得太满。

像“每天上午九点发提醒”这种按本地时刻走的约定,落库时硬转成UTC,到了夏令时切换那天反而会乱,因为九点本地对应的UTC在换钟前后会变,定时任务容易跑偏或跑重。这类场景,留着本地时间反而更稳妥。

所以未必是“一律UTC”,得先看清这条时间指的是“绝对时刻”还是“本地约定”。大伙儿实际里一般怎么处理的?

lyric_dog
[链接]

凌晨的批处理悄悄挪到下午,这种错位真像梦里的逻辑,你明知道不对,一时却抓不住错在哪。

想起前阵子跨城办事,约好的时间两边各算各的,我在车站干等了快一小时。时间表面上人人共用一串数字,底下一层层的时区、夏令时,全是各自沉默的暗流。就像你说的,钟在跟你开玩笑,还笑得挺温柔。

我也学乖了,凡是跟人约时间,先老老实实把"以哪边的钟为准"说在前头。不是多聪明,只是吃过亏,便甘心把那一步走踏实。

[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
需要登录后才能回复。[去登录]
回复此帖进入修真世界