ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

TDengine 时区与自然时间单位完全指南:UTC 存储语义、POSIX/ISO 符号约定与自然单位窗口对齐

TDengine 时区与自然时间单位完全指南:UTC 存储语义、POSIX/ISO 符号约定与自然单位窗口对齐 TDengine 时区与自然时间单位完全指南UTC 存储语义、POSIX/ISO 符号约定与自然单位窗口对齐【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine本文基于 TDengine v3.4.1–v3.4.3 的官方时区文档完整讲解时区在时间字符串与 UTC 存储之间的转换语义、五层时区优先级体系、SET TIMEZONE/SET FIRST_DAY_OF_WEEK/taos.cfg三种配置入口以及TO_ISO8601、TIMETRUNCATE、INTERVAL和流任务TIMEZONE子句中自然时间单位天/周/月/季/年的对齐规则并结合仓库源码指出关键解析与校验位置帮助你在多时区工业物联网IIoT场景中正确配置、验证和排查时区相关问题。版本支持标记TDengine 时区与自然时间单位功能分版本交付。阅读下文时需注意版本标记标记含义无标记v3.4.1已支持v3.4.2v3.4.2起支持v3.4.3v3.4.3起支持v3.4.2中尚不可用时区概述TDengine 内部以UTC 时间戳int64存储所有时间数据。时区仅在时间字符串与 UTC 之间的转换时起作用写入时将本地时间字符串转为 UTC 存储读取时将 UTC 转为本地时间字符串展示。也就是说时区不参与存储本身只影响“字符串 ↔ UTC”双向转换的锚点。支持的时区格式IANA 名称推荐示例Asia/Shanghai、America/New_York。夏令时感知是。系统自动处理 DST夏令时跳变与切换。这是避免时区语义混淆的首选写法。POSIX 固定偏移示例08:00、-0500、Z、10、UTC08:00、UTC8。夏令时感知否。全年使用恒定偏移。支持范围-14:00至14:00。符号约定SET TIMEZONE、ALTER LOCAL、taos.cfg、TO_CHAR、TIMETRUNCATE均遵循POSIX 符号约定 UTC 以西即local UTC − offset。唯一例外TO_ISO8601的固定偏移参数使用 ISO 8601 符号约定local UTC offset。POSIX 固定偏移格式详解TDengine 的固定偏移时区格式遵循POSIXTZ环境变量规范的子集。完整的 POSIX 规范定义了如下格式STD offset [ DST [ dstoffset ] [ , rule ] ]其中STD是标准时间缩写offset是与 UTC 的偏移量DST和dstoffset用于夏令时定义rule用于夏令时切换规则。TDengine 支持的子集仅支持该规范中STD offset部分且STD只接受UTC一个值。不支持手动配置DST、dstoffset和rule。如需夏令时支持请使用 IANA 时区名称。TDengine 接受的固定偏移语法如下UTC offsetoffset字段格式带UTC前缀时小时可以是一位或两位数字分钟如使用必须是两位数字表示西向偏移的正号可以省略例如UTC8等价于UTC8UTC8:30等价于UTC8:30。不带UTC前缀时正负号不能省略支持±HH、±HHMM和±HH:MM。偏移量精确到分钟。UTC前缀不区分大小写utc8与UTC8等价。特殊值Z等价于00:00。POSIX 符号约定POSIX 标准定义本地时间与 UTC 的关系为local_time UTC - offset因此正号表示 UTC以西西时区本地时间比 UTC 慢负号-表示 UTC以东东时区本地时间比 UTC 快。这与 ISO 8601 的符号约定相反。例如写法POSIX 含义等效 IANA 时区08:00或UTC08:00UTC 以西 8 小时接近Pacific/Pitcairn太平洋-08:00或UTC-08:00UTC 以东 8 小时接近Asia/Shanghai北京时间05:30或UTC05:30UTC 以西 5.5 小时接近America/Bogota哥伦比亚-05:30或UTC-05:30UTC 以东 5.5 小时接近Asia/Kolkata印度ZUTC 本身Etc/UTC当省略UTC前缀时如08:00TDengine 仍按 POSIX 规则解析偏移量行为与带UTC前缀完全一致此时正负号不能省略。支持范围偏移量的有效范围为-14:00至14:00对应 UTC 以东 14 小时到 UTC 以西 14 小时。与 IANA 时区的区别POSIX 固定偏移不包含任何夏令时信息全年使用恒定偏移。如果目标地区存在夏令时如美国、欧洲应使用 IANA 名称以获得正确的 DST 自动切换。源码佐证时区字符串的解析与校验集中在 ttime.c 中——taosParseTime先检测时间串尾部是否带Z//-时区标记checkTzPresent再走parseTimeWithTz或本地化解析分支无效时区统一产生TSDB_CODE_PAR_INVALID_TIMEZONE错误码并输出Invalid timezone: value错误信息这与下文错误信息一节完全对应见 ttime.c#L55-L63。客户端侧在 clientImpl.c#L483 等处对SET TIMEZONE/ALTER LOCAL的时区值做同样校验。GMT、CST、EST等写法会被明确拒绝可从单元测试 nodesTestMain.cpp#L245-L262 中验证。时区优先级TDengine 采用五层时区优先级体系高层覆盖低层优先级名称设定方式说明最高SQL 级函数时区参数如TO_ISO8601(ts, 09:00)TO_ISO8601IANA 参数v3.4.2流任务TIMEZONE子句v3.4.3仅影响本条 SQL 或本流任务高连接级C APItaos_options_connectionSET TIMEZONEv3.4.2影响当前连接的所有 SQL中客户端全局客户端侧taos.cfg中timezone仅影响客户端本地时间展示低服务端全局服务端侧taos.cfg中timezone连接未设时区时服务端计算的回退最低系统默认操作系统自动检测最终兜底重要客户端全局时区仅影响客户端本地展示如SELECT ts的输出格式化不影响服务端计算。未通过连接级设置时区的连接服务端计算回退到服务端全局时区。设置时区SET TIMEZONE自v3.4.2设置当前连接的时区SET TIMEZONE Asia/Shanghai; SET TIMEZONE -08:00; -- POSIX: local UTC8效果同北京时间 SET TIMEZONE 08:00; -- POSIX: local UTC-8不是北京时间 SET TIMEZONE America/New_York;固定偏移的正负号遵循 POSIX 符号约定注意-08:00才是北京时间、08:00是太平洋 Pitcairn 时区。设置后当前连接里的“当前时间显示”和大多数“和本地日历有关”的操作都会使用这个时区例如SELECT ts这类时间列的显示SELECT NOW()/SELECT NOWTO_ISO8601(ts)这类按时区格式化时间的函数TODAY()带有自然时间边界的计算如TIMETRUNCATE(..., 1d/1w/1n...)、INTERVAL也可通过 C APItaos_options_connection在建立连接时设置时区效果等同于SET TIMEZONE。若希望当前连接按北京时间显示与计算可直接执行SET TIMEZONE Asia/Shanghai;查询当前时区SELECT TIMEZONE();返回当前连接当前生效的单个时区字符串回退链为连接级SET TIMEZONE/ C API 设置值 → 连接创建时快照的客户端全局时区 → 系统默认时区。配置文件设置在taos.cfg中配置全局时区仓库自带的示例配置见 taos.cfg#L79-L83其中UTC-8按 POSIX 约定即“UTC 以东 8 小时”timezone Asia/Shanghai timezone UTC-8 timezone UTC8 timezone 08:00支持的格式包括IANA 名称、Windows 标准时区名称如China Standard Time、固定偏移格式Z、±HH、±HHMM、±HH:MM、UTCH[:MM]、UTCH[:MM]和UTC-H[:MM]H为一位或两位数字UTC前缀不区分大小写。GMT/GMT±...不支持。未配置时使用操作系统检测的时区。服务端侧taos.cfg连接未通过SET TIMEZONE设置时区时服务端计算回退到此值。客户端侧taos.cfg仅影响客户端本地时间展示如SELECT ts的输出格式化不影响服务端计算。注意固定偏移写法遵循 POSIX 符号约定所有入口SET TIMEZONE、ALTER LOCAL、taos.cfg的正负号含义一致。建议使用 IANA 名称以避免混淆。ALTER LOCAL timezone ...和SET TIMEZONE ...的区别SET TIMEZONE只影响当前连接断开重连后即失效。ALTER LOCAL timezone ...修改的是当前客户端进程里的全局配置只会影响修改后新建的连接已经打开的旧连接不会立刻改变。一周起始日SET FIRST_DAY_OF_WEEK自v3.4.2设置当前连接的一周起始日SET FIRST_DAY_OF_WEEK 0; -- 周日起始 SET FIRST_DAY_OF_WEEK 1; -- 周一起始说明客户端配置参数firstDayOfWeek的默认值为4周四见下文配置表。上述 SQL 仅设置当前连接。取值范围为0–60周日1周一…6周六。源码佐证该语句的解析入口在 ANTLR/Parser 层——文法定义见 sql.y#L835cmd :: SET FIRST_DAY_OF_WEEK NK_INTEGER(A)并支持负号形式函数名形式FIRST_DAY_OF_WEEK()亦以noarg_func注册见 sql.y#L2526。取值越界时产生TSDB_CODE_PAR_INVALID_FIRST_DAY_OF_WEEK错误定义于 terror.c#L193。查询当前周起始日自v3.4.2SELECT FIRST_DAY_OF_WEEK();返回当前连接生效的周起始日设置结果为0..6的整数其中0周日1周一…6周六。配置文件设置自v3.4.2在客户端侧taos.cfg中配置firstDayOfWeek 4也可通过ALTER LOCAL firstDayOfWeek 0..6在当前客户端进程内动态修改。该配置只影响修改后的新连接已建立连接保持各自创建时的快照值。默认值为4周四与历史按 Unix epoch 取模的周对齐行为兼容。若客户端未显式配置启动时会尝试从操作系统读取一周起始日读取失败时回退到4。若希望按周统计从周一开始可执行SET FIRST_DAY_OF_WEEK 1;若希望从周日开始设置为0。影响范围自v3.4.2firstDayOfWeek影响所有以w周为单位的操作TIMETRUNCATE(ts, 1w)的对齐日INTERVAL(1w)的窗口起始日PERIOD(1w)的触发日v3.4.3SLIDING(1w)的触发日v3.4.3时间函数TO_ISO8601SELECT TO_ISO8601(ts) FROM t; -- 使用连接时区 SELECT TO_ISO8601(ts, 09:00) FROM t; -- 指定固定偏移ISO 8601 符号 SELECT TO_ISO8601(ts, UTC09:00) FROM t; -- 等价写法UTC 前缀会被剥离 SELECT TO_ISO8601(ts, America/New_York) FROM t; -- 指定 IANA 时区自 v3.4.2符号约定唯一例外TO_ISO8601是唯一使用ISO 8601 符号约定的入口——local UTC offset即08:00表示东八区北京时间。以下写法完全等价0800、08:00、UTC8、UTC0800、UTC08:00。其余入口SET TIMEZONE、taos.cfg、TO_CHAR、TIMETRUNCATE等均使用 POSIX 符号约定 西区。这是最容易踩坑的一点同一字符串08:00在SET TIMEZONE中表示西八区在TO_ISO8601中表示东八区。使用 IANA 时区时输出的偏移量随时刻的夏令时状态自动变化SET TIMEZONE America/New_York; --自 v3.4.2 SELECT TO_ISO8601(2026-01-15 12:00:00); -- ...T12:00:00-05:00 (EST, 冬令时) SELECT TO_ISO8601(2026-07-15 12:00:00); -- ...T12:00:00-04:00 (EDT, 夏令时)源码佐证TO_ISO8601的时区参数校验在标量函数实现 builtins.c#L453-L469 中完成分别对固定偏移格式错误Invalid timezone format与非法时区名Invalid timezone: %s给出不同错误信息。TIMETRUNCATE将时间戳截断到指定单位边界SELECT TIMETRUNCATE(ts, 1d) FROM t; -- 截断到当天 00:00:00 SELECT TIMETRUNCATE(ts, 1w) FROM t; -- 截断到一周起始日 00:00:00 SELECT TIMETRUNCATE(ts, 1n) FROM t; -- 截断到当月 1 日自 v3.4.2 SELECT TIMETRUNCATE(ts, 1q) FROM t; -- 截断到当季首月 1 日自 v3.4.2 SELECT TIMETRUNCATE(ts, 1y) FROM t; -- 截断到当年 1 月 1 日自 v3.4.2 SELECT TIMETRUNCATE(ts, 1d, America/New_York) FROM t; -- 指定时区自 v3.4.2支持的自然时间单位单位含义截断规则版本d天对齐到当天 00:00:00已支持w周对齐到一周起始日由firstDayOfWeek决定00:00:00已支持v3.4.2起尊重 firstDayOfWeekn月对齐到当月 1 日 00:00:00v3.4.2q季度对齐到当季首月 1 日 00:00:00Q11 月Q24 月Q37 月Q410 月v3.4.2y年对齐到当年 1 月 1 日 00:00:00v3.4.2示例SELECT TIMETRUNCATE(2026-03-15, 1n); -- 2026-03-01 00:00:00自 v3.4.2 SELECT TIMETRUNCATE(2026-05-15, 1q); -- 2026-04-01 00:00:00自 v3.4.2 SELECT TIMETRUNCATE(2026-08-15, 1y); -- 2026-01-01 00:00:00自 v3.4.2第三参数时区值行为版本0使用 UTC旧语义已支持1使用连接时区旧语义已支持Asia/Shanghai使用指定 IANA 时区v3.4.208:00使用指定固定偏移POSIX 约定v3.4.2省略使用连接时区已支持源码佐证自然时间单位含季度的解析的单元测试位于 ttimeQuarterParseTest.cpp 与 ttimeNaturalUnitsTest.cpp覆盖了月/季/年边界的解析行为可作为对齐规则的实现级验证依据。TIMEZONE()SELECT TIMEZONE();返回当前连接当前使用的单个时区字符串当前连接执行过SET TIMEZONE时优先返回连接级时区。未设置连接级时区时返回该连接创建时快照的客户端全局时区若客户端也未配置则回退到系统默认时区。ALTER LOCAL timezone只会影响修改后新建的连接不会回写已有连接的TIMEZONE()结果。若需确认SET TIMEZONE是否生效可执行SELECT TIMEZONE(); SELECT TO_ISO8601(NOW());例如执行SET TIMEZONE Asia/Shanghai后TIMEZONE()返回Asia/Shanghai。未执行SET TIMEZONE时返回连接创建时快照的客户端全局时区。执行ALTER LOCAL timezone Asia/Shanghai后已有连接不受影响新建连接才会使用新配置。INTERVAL 查询INTERVAL支持按自然时间单位切分窗口SELECT _wstart, COUNT(*) FROM meters INTERVAL(1n) -- 按月切分自 v3.4.2 FILL(PREV); SELECT _wstart, AVG(voltage) FROM meters INTERVAL(1q) -- 按季度切分自 v3.4.2 FILL(NULL); SELECT _wstart, SUM(energy) FROM meters INTERVAL(1w) -- 按周切分尊重 firstDayOfWeek[v3.4.2] FILL(LINEAR);支持的自然时间单位单位窗口边界版本d本地时区每天 00:00:00已支持w本地时区一周起始日 00:00:00由firstDayOfWeek决定v3.4.2n本地时区每月 1 日 00:00:00v3.4.2q本地时区每季度首月 1 日 00:00:00v3.4.2y本地时区每年 1 月 1 日 00:00:00v3.4.2多倍数窗口INTERVAL(2q) -- 半年窗口[1 月7 月), [7 月次年 1 月)自 v3.4.2 INTERVAL(3n) -- 季度窗口等价 1q1/4/7/10 月自 v3.4.2 INTERVAL(2w) -- 双周窗口自 v3.4.2夏令时处理窗口始终按本地挂钟时间对齐。DST 切换日窗口物理时长会变化如春跳日 1d 窗口为 23 小时这是正确行为。写入/查询在夏令时跳变与重叠区间的注意点详见 夏令时使用指南。闰年/变长月窗口宽度自动适应实际天数如 2 月窗口 28 或 29 天。FILL填充边界逐月/逐季推进。流式计算时区流任务 TIMEZONE 子句自v3.4.3v3.4.3之前流式计算触发侧自然时间边界对齐始终使用服务端全局时区无法为单个流任务指定独立时区。v3.4.3起新增TIMEZONE子句为流任务指定独立时区适用于所有触发类型-- PERIOD 触发东京时区每周触发 CREATE STREAM weekly_tokyo TRIGGER PERIOD(1w) TIMEZONE Asia/Tokyo INTO tokyo_weekly AS SELECT AVG(current) FROM meters; -- SLIDING 触发纽约时区每季度滑动 CREATE STREAM slide_ny TRIGGER SLIDING(1q) TIMEZONE America/New_York FROM meters INTO ny_quarterly AS SELECT _tprev_ts, _tcurrent_ts, AVG(current) FROM %%trows; -- INTERVAL 触发伦敦时区月窗口 CREATE STREAM monthly_uk TRIGGER INTERVAL(1n) SLIDING(1w) TIMEZONE Europe/London FROM meters INTO uk_monthly AS SELECT _wstart, _wend, AVG(current) FROM %%trows; -- EVENT 触发计算侧使用东京时区 CREATE STREAM event_tokyo TRIGGER EVENT_WINDOW(START WITH voltage 220 END WITH voltage 220) TIMEZONE Asia/Tokyo FROM meters PARTITION BY tbname INTO event_out AS SELECT _twstart, _twend, AVG(current) FROM %%trows;固化行为TIMEZONE在创建时固化到流元数据。后续修改全局时区不影响已有流任务。未指定 TIMEZONE 时按连接时区 → 服务端全局时区 → OS 时区的顺序解析后固化。流式计算时区的影响影响位置说明触发侧PERIOD/SLIDING/INTERVAL自然单位d/w/n/q/y的日历边界对齐使用固化时区计算侧AS subqueryINTERVAL 自然单位窗口切分使用固化时区和 firstDayOfWeek流触发自然单位支持以下表格列出 PERIOD、SLIDING、INTERVAL 三种触发类型支持的时间单位及其版本PERIOD 触发单位含义版本a毫秒已支持s秒已支持m分钟已支持h小时已支持d天已支持w周已支持n月已支持y年已支持q季度v3.4.3offset 示例PERIOD(1w, 1d) -- 每周二 00:00:00 触发 PERIOD(1n, 14d) -- 每月 15 日 00:00:00 触发 PERIOD(1y, 31d) -- 每年 2 月 1 日 00:00:00 触发 PERIOD(1q) -- 每季度首月 1 日 00:00:00 触发自 v3.4.3 PERIOD(1q, 15d) -- 每季度第 16 日触发自 v3.4.3SLIDING 触发单位含义版本a毫秒已支持s秒已支持m分钟已支持h小时已支持d天已支持w周已支持n月v3.4.3q季度v3.4.3y年v3.4.3SLIDING(1n) -- 每月滑动触发自 v3.4.3 SLIDING(1q) -- 每季度滑动触发自 v3.4.3 SLIDING(1y) -- 每年滑动触发自 v3.4.3 SLIDING(1q, 15d) -- 每季度第 16 日滑动触发自 v3.4.3INTERVAL 窗口触发interval_val 和 sliding_val 均适用单位含义版本a毫秒已支持s秒已支持m分钟已支持h小时已支持d天v3.4.3w周v3.4.3n月v3.4.3q季度v3.4.3y年v3.4.3INTERVAL(1n) SLIDING(1w) -- 月窗口每周滑动自 v3.4.3 INTERVAL(1q) SLIDING(1n) -- 季度窗口每月滑动自 v3.4.3 INTERVAL(1y) SLIDING(1q) -- 年窗口每季度滑动自 v3.4.3 INTERVAL(1w) SLIDING(1d) -- 周窗口每天滑动自 v3.4.3查看流任务时区自v3.4.3SELECT stream_name, timezone, first_day_of_week FROM information_schema.ins_streams;ins_streams系统的timezone与first_day_of_week两列用于核对流任务创建时固化的时区与周起始日是排查“为什么我的流触发时间不对”类问题的第一现场。各场景时区来源速查场景时区来源版本说明写入INSERT连接 → 服务端全局 → OS将时间字符串转为 UTC已支持读取SELECT ts连接 → 客户端全局 → OS将 UTC 格式化为本地时间连接级回退为v3.4.2起支持此前仅用 OS 时区函数TO_ISO8601等SQL 参数 → 连接 → 服务端全局 → OS固定偏移参数已支持IANA 参数为v3.4.2TIMETRUNCATESQL 参数 → 连接 → 服务端全局 → OSd/w已支持n/q/y为v3.4.2时区字符串参数为v3.4.2INTERVAL查询窗口连接 → 服务端全局 → OSd已支持w/n/q/y为v3.4.2SHOW/EXPLAIN连接 → 客户端全局 → OS连接级回退为v3.4.2起支持此前仅用 OS 时区流式计算触发与计算服务端全局 → OSv3.4.3起支持TIMEZONE子句 → 连接 → 服务端全局 → OS创建时固化v3.4.3前使用服务端时区v3.4.3起支持固化这张表是运维排查的核心索引出现“同一条数据客户端 A 看到的ts与客户端 B 不同”时先定位所属场景再按回退链逐层核对。配置参数一览参数配置文件类型默认值说明版本timezone服务端/客户端侧taos.cfg字符串OS 检测全局时区已支持firstDayOfWeek客户端侧taos.cfg整数 0-64周四一周起始日也可用ALTER LOCAL动态修改v3.4.2错误信息错误场景错误信息无效时区字符串[0x26B2] Invalid timezone: valuefirstDayOfWeek 超出范围[0x26B3] Invalid firstDayOfWeek: value, must be 0-6两条错误信息分别在 ttime.c#L58 与 terror.c#L193 中定义出现0x26B2时优先检查时区字符串是否落在“IANA 名称 / 固定偏移”两类合法格式内GMT前缀、带 DST 规则的 POSIX 写法均会被拒绝。版本支持矩阵功能v3.4.2之前v3.4.2v3.4.3timezone配置文件服务端/客户端✅✅✅TO_ISO8601固定偏移参数✅✅✅TIMETRUNCATEd/w截断✅✅✅INTERVAL查询d窗口✅✅✅TIMEZONE()函数✅✅增强✅PERIOD 触发a/s/m/h/d/w/n/y✅✅✅SLIDING 触发a/s/m/h/d/w✅✅✅INTERVAL 窗口触发a/s/m/h✅✅✅SET TIMEZONE❌✅✅SET FIRST_DAY_OF_WEEK❌✅✅firstDayOfWeek配置参数❌✅✅TO_ISO8601IANA 时区参数❌✅✅TIMETRUNCATE时区字符串参数❌✅✅TIMETRUNCATEn/q/y截断❌✅✅INTERVAL查询w/n/q/y窗口❌✅✅普通列读取使用连接时区❌✅✅SHOW/EXPLAIN 使用连接时区❌✅✅流任务TIMEZONE子句❌❌✅流任务时区/firstDayOfWeek 固化❌❌✅PERIOD 触发q季度❌❌✅SLIDING 触发n/q/y❌❌✅INTERVAL 窗口触发d/w/n/q/y❌❌✅ins_streamstimezone/first_day_of_week 列❌❌✅小结与常见陷阱先记符号除TO_ISO8601外一切固定偏移入口都是 POSIX 约定——-08:00才是北京时间08:00是太平洋时区。拿不准时直接用Asia/Shanghai这样的 IANA 名称。分清展示与计算客户端taos.cfg的timezone只管客户端本地展示服务端计算窗口对齐、自然单位切分用连接时区或服务端全局时区二者不同源。连接快照语义SET TIMEZONE随连接生命周期存在ALTER LOCAL只影响后续新建连接TIMEZONE()是核对当前连接实际时区的唯一可靠手段。流任务固化v3.4.3起流任务时区在CREATE STREAM时固化之后改全局配置不会回溯改变已有流可通过information_schema.ins_streams的timezone列核对。周对齐看 firstDayOfWeek所有w单位操作的对齐日由firstDayOfWeek默认4即周四决定跨地区统一周统计时应在客户端taos.cfg或连接级显式设置。【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表