跳到主要内容

时区与自然时间单位

本文档描述 TDengine 时区语义与自然时间单位的完整状态。功能分版本交付,文中以版本号标注:

标记含义
(无标记)v3.4.1 已支持
[v3.4.2]v3.4.2 起支持
[v3.4.3]v3.4.3 起支持(v3.4.2 中尚不可用)

时区概述

TDengine 内部以 UTC 时间戳(int64)存储所有时间数据。时区仅在时间字符串与 UTC 之间的转换时起作用:写入时将本地时间字符串转为 UTC,读取时将 UTC 转为本地时间字符串展示。

支持的时区格式

格式示例夏令时感知说明
IANA 名称'Asia/Shanghai''America/New_York'✅ 是(自动处理 DST 跳变)推荐。系统自动处理夏令时切换。
POSIX 固定偏移'+08:00''-0500''Z''+10''UTC+08:00'❌ 否(恒定偏移)支持范围为 -14:00+14:00SET TIMEZONEALTER LOCALtaos.cfgTO_CHARTIMETRUNCATE 均遵循 POSIX 符号约定(+ = UTC 以西,即 local = UTC − offset)。例外TO_ISO8601 的固定偏移参数使用 ISO 8601 符号约定。详见下文"POSIX 固定偏移格式详解"。

POSIX 固定偏移格式详解

TDengine 的固定偏移时区格式遵循POSIX TZ 环境变量规范的子集。完整的 POSIX 规范定义了如下格式:

STD offset [ DST [ dstoffset ] [ , rule ] ]

其中 STD 是标准时间缩写,offset 是与 UTC 的偏移量,DSTdstoffset 用于夏令时定义,rule 用于夏令时切换规则。

TDengine 支持的子集:TDengine 仅支持该规范中 STD offset 部分,且 STD 只接受 UTC 一个值。不支持手动配置 DSTdstoffsetrule。如需夏令时支持,请使用 IANA 时区名称。TDengine 接受的固定偏移语法如下:

UTC offset

offset 字段格式offset 表示与 UTC 的偏移量,格式为 [+|-] hh [ : mm [ : ss ] ],其中 hh 可以是一位或两位数字,mmss(如使用)必须是两位数字。也可写为无冒号分隔的紧凑形式(如 +0800-0530)。特殊值 Z 等价于 +00:00

POSIX 符号约定:POSIX 标准定义本地时间与 UTC 的关系为:

local_time = UTC - offset

因此:正号 + 表示 UTC 以西(西时区,本地时间比 UTC 慢),负号 - 表示 UTC 以东(东时区,本地时间比 UTC 快)。这与 ISO 8601 的符号约定相反。例如:

写法POSIX 含义等效 IANA 时区
'+08:00''UTC+08:00'UTC 以西 8 小时接近 Pacific/Pitcairn(太平洋)
'-08:00''UTC-08:00'UTC 以东 8 小时接近 Asia/Shanghai(北京时间)
'+05:30''UTC+05:30'UTC 以西 5.5 小时接近 America/Bogota(哥伦比亚)
'-05:30''UTC-05:30'UTC 以东 5.5 小时接近 Asia/Kolkata(印度)
'Z'UTC 本身Etc/UTC

当省略 UTC 前缀时(如 '+08:00'),TDengine 仍按 POSIX 规则解析偏移量,行为与带 UTC 前缀完全一致。

支持范围:偏移量的有效范围为 -14:00+14:00(对应 UTC 以东 14 小时到 UTC 以西 14 小时)。

与 IANA 时区的区别:POSIX 固定偏移不包含任何夏令时信息,全年使用恒定偏移。如果目标地区存在夏令时(如美国、欧洲),应使用 IANA 名称以获得正确的 DST 自动切换。

时区优先级

TDengine 采用五层时区优先级体系,高层覆盖低层:

优先级名称设定方式说明
最高SQL 级函数时区参数(如 TO_ISO8601(ts, '+09:00'));TO_ISO8601 IANA 参数 [v3.4.2];流任务 TIMEZONE 子句 [v3.4.3]仅影响本条 SQL 或本流任务
连接级C API taos_options_connectionSET TIMEZONE [v3.4.2]影响当前连接的所有 SQL
客户端全局客户端侧 taos.cfgtimezone仅影响客户端本地时间展示
服务端全局服务端侧 taos.cfgtimezone连接未设时区时服务端计算的回退
最低系统默认操作系统自动检测最终兜底

重要:客户端全局时区仅影响客户端本地展示(如 SELECT ts 的输出格式化),不影响服务端计算。未通过连接级设置时区的连接,服务端计算回退到服务端全局时区。

设置时区

SET TIMEZONE [v3.4.2]

设置当前连接的时区:

SET TIMEZONE 'Asia/Shanghai';
SET TIMEZONE '-08:00'; -- POSIX: local = UTC+8,效果同北京时间
SET TIMEZONE '+08:00'; -- POSIX: local = UTC-8,不是北京时间
SET TIMEZONE 'America/New_York';

固定偏移的正负号遵循 POSIX 符号约定,详见上文"POSIX 固定偏移格式详解"。

设置后,当前连接里的“当前时间显示”和大多数“和本地日历有关”的操作都会使用这个时区,例如:

  • SELECT ts 这类时间列的显示
  • SELECT NOW() / SELECT NOW
  • TO_ISO8601(ts) 这类按时区格式化时间的函数
  • TODAY()
  • 带有自然时间边界的计算,如 TIMETRUNCATE(..., 1d/1w/1n...)INTERVAL

也可通过 C API taos_options_connection 在建立连接时设置时区,效果等同于 SET TIMEZONE

如果你只是想“当前连接按北京时间看时间”,最直接的写法就是:

SET TIMEZONE 'Asia/Shanghai';

查询当前时区

SELECT TIMEZONE();

返回当前连接当前生效的单个时区字符串,回退链为连接级 SET TIMEZONE / C API 设置值 → 连接创建时快照的客户端全局时区 → 系统默认时区。

可以简单理解为:TIMEZONE() 告诉你“这个连接现在到底按哪个时区在工作”。

配置文件设置

taos.cfg 中配置全局时区:

timezone Asia/Shanghai
timezone UTC-8
timezone +08:00

支持 IANA 名称、Windows 标准时区名称(如 China Standard Time)以及固定偏移格式 Z±HH±HHMM±HH:MMUTC±H[:MM]UTC±HH[:MM]GMT / GMT±... 不支持。未配置时使用操作系统检测的时区。

  • 服务端侧 taos.cfg:连接未通过 SET TIMEZONE 设置时区时,服务端计算回退到此值。
  • 客户端侧 taos.cfg:仅影响客户端本地时间展示(如 SELECT ts 的输出格式化),不影响服务端计算。

注意:固定偏移写法遵循 POSIX 符号约定(详见"POSIX 固定偏移格式详解"),所有入口(SET TIMEZONEALTER LOCALtaos.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; -- 周一起始(默认)

取值范围 0-6:0=周日,1=周一,..., 6=周六。

查询当前周起始日 [v3.4.2]

SELECT 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.2]

firstDayOfWeek 影响所有以 w(周)为单位的操作:

  • TIMETRUNCATE(ts, 1w) 的对齐日
  • INTERVAL(1w) 的窗口起始日
  • PERIOD(1w) 的触发日 [v3.4.3]
  • SLIDING(1w) 的触发日 [v3.4.3]

时间函数

TO_ISO8601

SELECT TO_ISO8601(ts) FROM t;                        -- 使用连接时区
SELECT TO_ISO8601(ts, '+09:00') FROM t; -- 指定固定偏移(ISO 8601 符号)
SELECT TO_ISO8601(ts, 'UTC+09: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''UTC+8''UTC+0800''UTC+08:00'。其余入口(SET TIMEZONEtaos.cfgTO_CHARTIMETRUNCATE 等)均使用 POSIX 符号约定(+ = 西区)。

使用 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, 夏令时)

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 起尊重 firstDayOfWeek
n对齐到当月 1 日 00:00:00v3.4.2
q季度对齐到当季首月 1 日 00:00:00(Q1=1 月,Q2=4 月,Q3=7 月,Q4=10 月)v3.4.2
y对齐到当年 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.2
'+08:00'使用指定固定偏移v3.4.2
省略使用连接时区已支持

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.2
n本地时区每月 1 日 00:00:00v3.4.2
q本地时区每季度首月 1 日 00:00:00v3.4.2
y本地时区每年 1 月 1 日 00:00:00v3.4.2

多倍数窗口

INTERVAL(2q)   -- 半年窗口:[1 月,7 月), [7 月,次年 1 月) [v3.4.2]
INTERVAL(3n) -- 季度窗口(等价 1q):1/4/7/10 月 [v3.4.2]
INTERVAL(2w) -- 双周窗口 [v3.4.2]

夏令时处理:窗口始终按本地挂钟时间对齐。DST 切换日窗口物理时长会变化(如春跳日 1d 窗口为 23 小时),这是正确行为。

闰年/变长月:窗口宽度自动适应实际天数(如 2 月窗口 28 或 29 天)。FILL 填充边界逐月/逐季推进。

流计算时区

流任务 TIMEZONE 子句 [v3.4.3]

v3.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 subquery)INTERVAL 自然单位窗口切分使用固化时区和 firstDayOfWeek

流触发自然单位支持

以下表格列出 PERIOD、SLIDING、INTERVAL 三种触发类型支持的时间单位及其版本:

PERIOD 触发

单位含义版本
a毫秒已支持
s已支持
m分钟已支持
h小时已支持
d已支持
w已支持
n已支持
y已支持
q季度v3.4.3

offset 示例

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.3]

SLIDING 触发

单位含义版本
a毫秒已支持
s已支持
m分钟已支持
h小时已支持
d已支持
w已支持
nv3.4.3
q季度v3.4.3
yv3.4.3
SLIDING(1n)          -- 每月滑动触发 [v3.4.3]
SLIDING(1q) -- 每季度滑动触发 [v3.4.3]
SLIDING(1y) -- 每年滑动触发 [v3.4.3]
SLIDING(1q, 15d) -- 每季度第 16 日滑动触发 [v3.4.3]

INTERVAL 窗口触发(interval_val 和 sliding_val 均适用):

单位含义版本
a毫秒已支持
s已支持
m分钟已支持
h小时已支持
dv3.4.3
wv3.4.3
nv3.4.3
q季度v3.4.3
yv3.4.3
INTERVAL(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.3]

SELECT stream_name, timezone, first_day_of_week FROM information_schema.ins_streams;

各场景时区来源速查

场景时区来源版本说明
写入 INSERT连接 → 服务端全局 → OS将时间字符串转为 UTC,已支持
读取 SELECT ts连接 → 客户端全局 → OS将 UTC 格式化为本地时间;连接级回退为 v3.4.2 起支持(此前仅用 OS 时区)
函数(TO_ISO8601 等)SQL 参数 → 连接 → 服务端全局 → OS固定偏移参数已支持;IANA 参数为 v3.4.2
TIMETRUNCATESQL 参数 → 连接 → 服务端全局 → OSd/w 已支持;n/q/yv3.4.2;时区字符串参数为 v3.4.2
INTERVAL 查询窗口连接 → 服务端全局 → OSd 已支持;w/n/q/yv3.4.2
SHOW / EXPLAIN连接 → 客户端全局 → OS连接级回退为 v3.4.2 起支持(此前仅用 OS 时区)
流计算触发与计算服务端全局 → OS;[v3.4.3] 起支持 TIMEZONE 子句 → 连接 → 服务端全局 → OS(创建时固化)v3.4.3 前使用服务端时区;v3.4.3 起支持固化

配置参数一览

参数配置文件类型默认值说明版本
timezone服务端/客户端侧 taos.cfg字符串OS 检测全局时区已支持
firstDayOfWeek客户端侧 taos.cfg整数 0-64(周四)一周起始日;也可用 ALTER LOCAL 动态修改v3.4.2

错误信息

错误场景错误信息
无效时区字符串[0x26B2] Invalid timezone: '<value>'
firstDayOfWeek 超出范围[0x26B3] Invalid firstDayOfWeek: <value>, must be 0-6

版本支持矩阵

功能v3.4.2 之前v3.4.2v3.4.3
timezone 配置文件(服务端/客户端)
TO_ISO8601 固定偏移参数
TIMETRUNCATE d/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_ISO8601 IANA 时区参数
TIMETRUNCATE 时区字符串参数
TIMETRUNCATE n/q/y 截断
INTERVAL 查询 w/n/q/y 窗口
普通列读取使用连接时区
SHOW/EXPLAIN 使用连接时区
流任务 TIMEZONE 子句
流任务时区/firstDayOfWeek 固化
PERIOD 触发 q 季度
SLIDING 触发 n/q/y
INTERVAL 窗口触发 d/w/n/q/y
ins_streams timezone/first_day_of_week 列