1、问题引入
先介绍一下上游数据:L1事件明细,记录了Web 侧事件级遥测数据,包含用户行为及部分系统/测试/机器人事件。此文件每一个小时记录会生成一个,每个大小为5-30TB左右。
假设当前时间为curr_time,我们需要得到curr_time-2h, curr_time-1h, curr_time, curr_time+1h共计四个文件才能开始当前时间为curr_time的计算任务。每两个小时开始一个这样的计算任务,也就是说一天需要完成12个并生成对应12个文件,每个计算任务完成都会在数据库插入一条记录。
目前的保障措施:因为上游数据数据达到的时间不确定,所以如果想保证计算任务顺利执行,在设计ETL流程时会根据当前时间预判可能的到达时间,并wait10h,在此期间如果需要的所有上游文件都到达就会触发计算任务。同时增加了对上游数据的监控,在规定时间范围内未到达就会触发通知。
但这样做还是有一个遗漏之处,就是是上游文件在规定时间范围内到达,但是由于计算任务时间过长或者计算量太大,就会导致计算任务无法准时完成。而目前监控计算任务是否完成只能通过肉眼去查文件是否生成。
因此引入我的任务:在grafana中新建一个dashboard来可视化计算任务的结果,用来判断计算任务是否完成 实现过程也很简单:去查对应时间的数据库内是否有计算任务完成的记录,构造本应在一天中生成的12个文件行,将其与数据库进行Join,对的上的标记为存在,对不上的标记为不存在。
在实现的过程中我发现自己踩了时区转化的坑,导致dashboard中展示的计算结果的create_time和实际create_time不同,具体踩坑点如下:
grafana的dashboard中有时间范围筛选,其默认时区为北京时间
Mysql数据库的时区为UTC时间
计算任务生成的结果存储在Azure云上,其时区为PDT时间
这样就导致了同一条记录在不同的地方查询显示/操作的create_time都是不同的,所以此文章介绍一下时区转换
2、时间解析
2.1 什么是 UTC 时间
2.1.1 UTC 是全球统一的时间基准
UTC 全称:
Coordinated Universal Time,协调世界时
它不是某个国家或城市的地方时间,而是全球系统进行时间同步时使用的基准。
常见表示方式:2026-07-31T06:30:00Z
2026-07-31:日期T:日期和时间的分隔符06:30:00:时、分、秒Z:表示 UTC,也叫 Zulu Time
2.1.2 UTC 和 GMT 的关系
日常业务中,UTC+0和GMT+0两者通常可以视为相同偏移:
但概念上并不完全相同:
- UTC:Coordinated Universal Time,现代时间标准,基于原子钟等时间体系。
- GMT: Greenwich Mean Time,格林尼治平均时,最初基于天文观测,也常被用作时区名称。
对于日志、数据库、API、Pipeline 和告警系统,建议统一使用 UTC,而不是 GMT。
2.2 什么是北京时间CST
北京时间CST,通常指:
China Standard Time(CST) ,常表示为 UTC+08:00
换算关系:
UTC: 2026-07-31 16:30,对应北京时间: 2026-08-01 00:30(注意,减去或加上 8 小时后,日期也可能变化)
2.2.1 北京时间没有夏令时切换
目前中国标准时间全年固定为:UTC+8
因此,在当前规则下:
- 夏天是 UTC+8
- 冬天也是 UTC+8
- 不存在北京时间突然跳过一小时或重复一小时的问题
不过,跨时区项目中不要把它简单写成模糊的 CST。因为 CST 可能被解释为:
- China Standard Time
- Central Standard Time
- Cuba Standard Time
更明确的写法是:UTC+08:00和 Asia/Shanghai
2.3 什么是 PST 和 PDT
PST 和 PDT 都与北美太平洋时区有关,他们是北美太平洋时区在不同月份范围的细分时区,但是可以统称为Pacific Time(缩写为PT),即PT = PST 或 PDT
按美国现行的一般规则,夏令时从每年 3 月第二个星期日开始,到 11 月第一个星期日结束。这个时间范围内采用PDT时区,剩余时间范围采用PST时区。
2.3.1 PST:Pacific Standard Time
太平洋标准时间 Pacific Standard Time (缩写PST),主要对应不使用夏令时(DST)的时期
UTC 偏移:UTC-8(比 UTC 慢 8 小时)
使用地区:美国西海岸(加州、华盛顿州、俄勒冈州、内华达州等)、加拿大不列颠哥伦比亚省,主要城市包括洛杉矶、旧金山、西雅图、波特兰、温哥华
启用时段:每年 11 月第一个星期日到次年 3 月第二个星期日(即冬令时)
夏令时切换:3 月第二个星期日起切换为 PDT(UTC-7),11 月第一个星期日回切到 PST
2.3.2 PDT:Pacific Daylight Time
太平洋夏令时间 Pacific Daylight Time(PDT) 在实行夏令时期间使用
UTC 偏移:PDT = UTC-7(比 UTC 晚 7 小时)
使用地区:美国西海岸(加州、华盛顿州、内华达州、俄勒冈州等)、加拿大不列颠哥伦比亚省,主要城市包括洛杉矶、旧金山、西雅图、波特兰、温哥华等
启用时段:每年 3 月第二个星期日到 11 月第一个星期日
冬令时切换:夏令时结束后切换回 PST(Pacific Standard Time,太平洋标准时间,UTC-8)
💡 注意:PDT 只在夏令时期间有效(3 月中~11 月初)。其余月份美国西海岸用的是 PST(UTC-8)。如果你的业务时间跨度覆盖全年,不能简单地固定减 7 小时,应该用命名时区让 MySQL 自动处理切换:
| |
2.3.3 PST 与 PDT 的关系
两者指的是同一个地理区域的同一条时间线,只是根据季节在"标准时间"和"夏令时"之间切换:
| 时段 | 缩写 | 全称 | UTC 偏移 |
|---|---|---|---|
| 冬季(11 月~3 月) | PST | Pacific Standard Time | UTC-8 |
| 夏季(3 月~11 月) | PDT | Pacific Daylight Time | UTC-7 |
也就是说,PDT = PST + 1 小时。夏令时开始时时钟拨快 1 小时(PST → PDT),结束时拨慢 1 小时(PDT → PST)。
💡 所以严格来说,“Pacific Time(PT)“是一个统称,它底下分 PST 和 PDT 两种状态,随季节切换。
2.4 PST/PDT 与北京时间相差多少
已知:
PDT = UTC-7,PST = UTC-8,北京时间 = UTC+8
所以可以得出:
| 太平洋当地时间 | UTC 偏移 | 与北京时间的时差 |
|---|---|---|
| PST | UTC-8 | CST=PST+16H |
| PDT | UTC-7 | CST=PST+15H |
3、跨时区项目一般怎么处理
原则一:后端和数据层统一使用 UTC
建议以下内容全部保存为 UTC:
- 数据库时间字段
- Pipeline 的运行时间
- 文件到达时间
- 日志时间
- API 请求时间
- 事件发生时间
- 告警检测时间
- 消息队列中的时间
- 分布式系统 Watermark
- 审计记录
例如:2026-07-31T06:30:00Z
而不是只保存:2026-07-31 14:30:00
后者没有说明时区,无法判断它是北京时间、UTC 还是美国当地时间。
原则二:展示时才转成用户当地时间
典型流程是:
| |
4、我的项目怎么处理
因为想的是替换掉手动去云存储那里一个个查文件的过程,所以dashboard这里显示的时间要和云存储的create_time一致
| |
针对目标查询表加一层view视图,将转为洛杉矶当地时间,如下
| |
如果转换完得到的时间为NULL,是因为MySQL 必须查询内部时区表,以确定:
America/Los_Angeles是否存在- 2026 年 7 月 31 日是否处于夏令时
- 此时应该使用 UTC-7 还是 UTC-8
- 夏令时切换边界如何处理
当前 MySQL 查不到对应的时区规则,因此返回 NULL。解决办法详见下面的4.1、4.2、4.3
4.1 查看MySQL Server 和 Session 当前使用的时区
| |
返回
| system_time_zone | global_time_zone | session_time_zone |
|---|---|---|
| China Standard Time | SYSTEM | SYSTEM |
4.2 查看命名时区表是否已经加载
| |
返回
| timezone_count |
|---|
| 0 |
4.3 开启时区数据库
要在 MySQL 中使用命名时区(如 'America/Los_Angeles'、'Asia/Shanghai'),必须先把系统的 IANA 时区数据库(zoneinfo)加载进 MySQL 自带的 mysql.time_zone_* 系统表里。否则 CONVERT_TZ 用命名时区时会返回 NULL。
4.3.1 windows系统
windows系统则首先下载 MySQL 时区包:MySQL :: Time zone description tables,选择timezone_2026c_posix_sql.zip,解压到对应位置(我的位置是:C:\Users\v-liuyuhang\AppData\Roaming\DBeaverData\workspace6\General\timezone_posix.sql) 打开cmd,进入mysql.exe所在目录,我的是 C:\Program Files\MySQL\MySQL Server 8.4\bin
执行命令:
| |
4.3.2 Linux系统
大多数 Linux 发行版和 macOS 在 /usr/share/zoneinfo 下都有 IANA 数据库,直接用一行管道加载
| |
4.3.4 云数据库
| |
然后弹出 Enter password: 输入密码
4.3.3 验证
| |
返回
| mysql_original_time | los_angeles_time | beijing_time |
|---|---|---|
| 2026-07-31 17:36:02 | 2026-07-31 10:36:02 | 2026-08-01 01:36:02 |