如何在SQL Server中利用AT TIME ZONE实现多国时区换算

胖明大大_8569

胖明大大_8569

2026-10-23

826人浏览

原创

at time zone 不能直接跨时区转换,必须经 utc 中转:先将无时区 datetime2 按源时区解释为 utc,再转为目标时区本地时间;时区名须用 windows 标识符,且需注意夏令时与历史偏移。

如何在sql server中利用at time zone实现多国时区换算

AT TIME ZONE 不能直接转换任意两个时区,必须经过 UTC 中转

SQL Server 的 AT TIME ZONE 不是“从 A 时区直接转到 B 时区”的函数,它只做两件事:把一个无时区的 datetime2 解释为某个时区的本地时间(→ UTC),或把 UTC 时间转换为指定时区的本地时间(UTC →)。所以跨时区换算本质是两步:原时间 AT TIME ZONE '源时区' → 转成 UTC datetime2,再 AT TIME ZONE '目标时区'。

常见错误是写成 GETDATE() AT TIME ZONE 'China Standard Time' AT TIME ZONE 'Pacific Standard Time' —— 这会先按 CST 解释当前服务器时间(错!因为 GETDATE() 返回的是本地服务器时区时间,不是 CST),再转 PST,结果完全不可靠。

  • 必须确保输入时间是 datetime2 类型且不带时区信息(即 datetime2 值本身是“纯时间点”,不隐含解释)
  • 若原始数据来自应用层,建议统一存为 UTC,避免源头歧义
  • 时区名称必须用 Windows 时区标识符(如 'China Standard Time',不是 'Asia/Shanghai'),可用 sys.time_zone_info 查看支持列表

如何正确把北京时间下午 3 点转成纽约时间

假设你有一条明确的北京时间(CST)时间点:2024-06-15 15:00:00,想得到对应纽约(Eastern Time)本地时间。关键在于:这个“15:00”是 CST 的本地时间,不是服务器时间,也不是 UTC。

SELECT 
  CAST('2024-06-15T15:00:00' AS datetime2) AT TIME ZONE 'China Standard Time' 
    AT TIME ZONE 'Eastern Standard Time' AS ny_time;

执行过程:
• 第一步:把字符串转成 datetime2,再用 AT TIME ZONE 'China Standard Time' 将其解释为 CST 本地时间 → 得到带偏移的 datetimeoffset(即 UTC 时间)
• 第二步:该 datetimeoffset 自动作为 UTC 输入,再经 AT TIME ZONE 'Eastern Standard Time' 转为 ET 本地时间

  • 注意:夏季用 'Eastern Daylight Time' 更准确;SQL Server 不自动处理夏令时切换,它依赖系统时区库,而 Windows 时区名(如 'Eastern Standard Time')本身已包含 DST 规则
  • 如果原始时间字段是 datetime 类型,务必先转成 datetime2,否则精度丢失且 AT TIME ZONE 会静默失败
  • 结果列类型是 datetimeoffset,若只要本地时间值(去掉偏移),可外裹 CAST(... AS datetime2)

批量转换表中带时区标记的时间字段

当表里已有 datetime2 列 + 单独的 timezone_name 列(如 'Tokyo Standard Time'、'GMT Standard Time'),需动态转成统一目标时区(如 UTC 或 ‘W. Europe Standard Time’)。这时不能直接在 AT TIME ZONE 中用变量或列名——它不接受表达式作为时区参数。

可行方案是用 CASE 显式枚举(适用于时区种类有限),或改用 TRY_CAST + 多次 UNION ALL 拆解(不推荐),更稳妥的是在应用层处理,或用标量函数封装(但有性能代价):

SELECT 
  id,
  event_time,
  timezone_name,
  CASE timezone_name
    WHEN 'China Standard Time' THEN event_time AT TIME ZONE 'China Standard Time'
    WHEN 'Tokyo Standard Time' THEN event_time AT TIME ZONE 'Tokyo Standard Time'
    WHEN 'GMT Standard Time' THEN event_time AT TIME ZONE 'GMT Standard Time'
    ELSE NULL
  END AT TIME ZONE 'W. Europe Standard Time' AS time_in_rome
FROM events;
  • AT TIME ZONE 的时区参数必须是字符串字面量,不能是变量、列或拼接结果
  • 大量不同源时区时,建议提前将源时间统一转为 UTC 存储,后续转换更高效、可索引
  • 注意 sys.time_zone_info 中的 current_utc_offset 是当前偏移,不反映历史变化(如 1986 年中国未实行夏令时),所以历史时间转换需额外校验

为什么有时转换后时间没变,甚至倒退一小时

典型现象:把某时间从 'Pacific Standard Time' 转到 'Pacific Daylight Time',结果却显示相同时间点,或出现“2:30 AM 重复”“跳过 2:00 AM”等异常。这不是 bug,而是 Windows 时区数据库对夏令时过渡的精确建模所致。

例如:2024 年 3 月 10 日凌晨 2:00,美国太平洋时间进入夏令时,时钟拨快至 3:00 —— 那么 '2024-03-10T02:30:00' AT TIME ZONE 'Pacific Standard Time' 实际不存在(标准时间下该时刻被跳过),SQL Server 会按规则映射到最近有效时间(通常是 3:30)。

  • 用 sys.time_zone_info 查看各时区的 is_currently_dst 和历史 utc_offset 变化点
  • 避免在 DST 切换小时内做精确时间比对(如排班、日志对齐),优先用 UTC 存储和计算
  • 测试时别只用今天,一定要覆盖 3 月/11 月前后几天,验证是否触发了 DST 边界逻辑
时区转换真正难的不是语法,而是确认每个时间值的语义归属:它到底是“某地的墙上时间”,还是“已知的 UTC 瞬间”,抑或“服务器本地时间”。一旦源头定义模糊,AT TIME ZONE 再准也没用。
PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.11

5831

4

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

2023.06.29

2805

3

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2023.08.14

4001

10

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

2023.08.31

3111

3

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.05

987

5

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.09

2727

5

数据库对象名无效怎么解决
数据库对象名无效怎么解决

数据库对象名无效解决办法:1、检查使用的对象名是否正确,确保没有拼写错误;2、检查数据库中是否已存在具有相同名称的对象,如果是,请更改对象名为一个不同的名称,然后重新创建;3、确保在连接数据库时使用了正确的用户名、密码和数据库名称;4、尝试重启数据库服务,然后再次尝试创建或使用对象;5、尝试更新驱动程序,然后再次尝试创建或使用对象。

2023.10.16

2727

4

vb连接access数据库的方法
vb连接access数据库的方法

vb连接access数据库方法:1、使用ADO连接,首先导入System.Data.OleDb模块,然后定义一个连接字符串,接着创建一个OleDbConnection对象并使用Open() 方法打开连接;2、使用DAO连接,首先导入 Microsoft.Jet.OLEDB模块,然后定义一个连接字符串,接着创建一个JetConnection对象并使用Open()方法打开连接即可。

2023.10.16

2913

3

vb连接数据库的方法
vb连接数据库的方法

vb连接数据库的方法有使用ADO对象库、使用OLEDB数据提供程序、使用ODBC数据源等。详细介绍:1、使用ADO对象库方法,ADO是一种用于访问数据库的COM组件,可以通过ADO连接数据库并执行SQL语句。可以使用ADODB.Connection对象来建立与数据库的连接,然后使用ADODB.Recordset对象来执行查询和操作数据;2、使用OLEDB数据提供程序方法等等。

2023.10.19

2541

3

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.9万人学习