Ian*_*oyd 36 sql-server internationalization sql-server-2008-r2
如何将SQL Server datetime值转换为datetimeoffset值?
例如,现有表包含datetime全部处于"本地"服务器时间的值.
SELECT TOP 5 ChangeDate FROM AuditLog
ChangeDate
=========================
2013-07-25 04:00:03.060
2013-07-24 04:00:03.073
2013-07-23 04:00:03.273
2013-07-20 04:00:02.870
2013-07-19 04:00:03.780
Run Code Online (Sandbox Code Playgroud)
我的服务器(恰好)(现在,今天)比UTC晚了四个小时(现在,在美国东部时区,夏令时处于活动状态):
SELECT SYSDATETIMEOFFSET()
2013-07-25 14:42:41.6450840 -04:00
Run Code Online (Sandbox Code Playgroud)
我想将存储的datetime值转换为datetimeoffset值; 使用服务器的当前时区偏移信息.
我想要的价值观是:
ChangeDate ChangeDateOffset
======================= ==================================
2013-07-25 04:00:03.060 2013-07-25 04:00:03.0600000 -04:00
2013-07-24 04:00:03.073 2013-07-24 04:00:03.0730000 -04:00
2013-07-23 04:00:03.273 2013-07-23 04:00:03.2730000 -04:00
2013-07-20 04:00:02.870 2013-07-20 04:00:02.8700000 -04:00
2013-07-19 04:00:03.780 2013-07-19 04:00:03.7800000 -04:00
Run Code Online (Sandbox Code Playgroud)
你可以看到理想的特征:
2013-07-19 04:00:03.7800000 -04:00
--------------------------- ------
| |
a "local" datetime the offset from UTC
Run Code Online (Sandbox Code Playgroud)
但相反,实际值是:
SELECT TOP 5
ChangeDate,
CAST(ChangeDate AS datetimeoffset) AS ChangeDateOffset
FROM AuditLog
ChangeDate ChangeDateOffset
======================= ==================================
2013-07-25 04:00:03.060 2013-07-25 04:00:03.0600000 +00:00
2013-07-24 04:00:03.073 2013-07-24 04:00:03.0730000 +00:00
2013-07-23 04:00:03.273 2013-07-23 04:00:03.2730000 +00:00
2013-07-20 04:00:02.870 2013-07-20 04:00:02.8700000 +00:00
2013-07-19 04:00:03.780 2013-07-19 04:00:03.7800000 +00:00
Run Code Online (Sandbox Code Playgroud)
具有无效特征:
2013-07-19 04:00:03.7800000 +00:00
--------------------------- ------
^
|
No offset from UTC present
Run Code Online (Sandbox Code Playgroud)
所以我随机尝试其他事情:
SELECT TOP 5
ChangeDate,
CAST(ChangeDate AS datetimeoffset) AS ChangeDateOffset,
DATEADD(minute, DATEDIFF(minute, GETDATE(), GETUTCDATE()), ChangeDate) AS ChangeDateUTC,
CAST(DATEADD(minute, DATEDIFF(minute, GETDATE(), GETUTCDATE()), ChangeDate) AS datetimeoffset) AS ChangeDateUTCOffset,
SWITCHOFFSET(CAST(ChangeDate AS datetimeoffset), DATEDIFF(minute, GETUTCDATE(), GETDATE())) AS ChangeDateSwitchedOffset
FROM AuditLog
ORDER BY ChangeDate DESC
Run Code Online (Sandbox Code Playgroud)
结果如下:
ChangeDate ChangeDateOffset ChangeDateUTC ChangeDateUTCOffset ChangeDateSwitchedOffset
======================= ================================== ======================= ================================== ==================================
2013-07-25 04:00:03.060 2013-07-25 04:00:03.0600000 +00:00 2013-07-25 08:00:03.060 2013-07-25 08:00:03.0600000 +00:00 2013-07-25 00:00:03.0600000 -04:00
2013-07-24 04:00:03.073 2013-07-24 04:00:03.0730000 +00:00 2013-07-24 08:00:03.073 2013-07-24 08:00:03.0730000 +00:00 2013-07-24 00:00:03.0730000 -04:00
2013-07-23 04:00:03.273 2013-07-23 04:00:03.2730000 +00:00 2013-07-23 08:00:03.273 2013-07-23 08:00:03.2730000 +00:00 2013-07-23 00:00:03.2730000 -04:00
2013-07-20 04:00:02.870 2013-07-20 04:00:02.8700000 +00:00 2013-07-20 08:00:02.870 2013-07-20 08:00:02.8700000 +00:00 2013-07-20 00:00:02.8700000 -04:00
2013-07-19 04:00:03.780 2013-07-19 04:00:03.7800000 +00:00 2013-07-19 08:00:03.780 2013-07-19 08:00:03.7800000 +00:00 2013-07-19 00:00:03.7800000 -04:00
---------------------------------- ---------------------------------- ----------------------------------
No UTC offset Time in UTC No UTC offset Time all wrong
Run Code Online (Sandbox Code Playgroud)
它们都没有返回所需的值.
任何人都可以建议回归我直觉所需的东西吗?
Ian*_*oyd 63
我想到了.诀窍是有一个内置的SQL Server函数ToDateTimeOffset,它将任意偏移信息附加到任何提供的datetime.
例如,相同的查询:
SELECT ToDateTimeOffset('2013-07-25 15:35:27', -240) -- -240 minutes
SELECT ToDateTimeOffset('2013-07-25 15:35:27', '-04:00') -- -4 hours
Run Code Online (Sandbox Code Playgroud)
两者都回归:
2013-07-25 15:35:27.0000000 -04:00
Run Code Online (Sandbox Code Playgroud)
注意:offset参数ToDateTimeOffset可以是:
integer,代表几分钟string,代表小时和分钟({+|-}TZH:THM格式)接下来我们需要服务器与UTC的当前偏移量.我有两种方法可以让SQL Server返回integerUTC的分钟数:
DATEPART(TZOFFSET, SYSDATETIMEOFFSET())
DATEDIFF(minute, GETUTCDATE(), GETDATE())
Run Code Online (Sandbox Code Playgroud)
都归来了
-240
Run Code Online (Sandbox Code Playgroud)
将其插入TODATETIMEOFFSET功能:
SELECT ToDateTimeOffset(
'2013-07-25 15:35:27',
DATEPART(TZOFFSET, SYSDATETIMEOFFSET()) --e.g. -240
)
Run Code Online (Sandbox Code Playgroud)
返回datetimeoffset我想要的值:
2013-07-25 15:35:27.0000000 -04:00
Run Code Online (Sandbox Code Playgroud)
现在我们可以有更好的功能将datetime转换为datetimeoffset:
CREATE FUNCTION dbo.ToDateTimeOffset(@value datetime2)
RETURNS datetimeoffset AS
BEGIN
/*
Converts a date/time without any timezone offset into a datetimeoffset value,
using the server's current offset from UTC.
For this we use the builtin ToDateTimeOffset function;
which attaches timezone offset information with a datetimeoffset value.
The trick is to use DATEDIFF(minutes) between local server time and UTC
to get the offset parameter.
For example:
DATEPART(TZOFFSET, SYSDATETIMEOFFSET())
returns the integer
-240
for people in EDT (Eastern Daylight Time), which is 4 hours (240 minutes) behind UTC.
Pass that value to the SQL Server function:
TODATETIMEOFFSET(@value, -240)
*/
RETURN TODATETIMEOFFSET(@value, DATEPART(TZOFFSET, SYSDATETIMEOFFSET()))
END;
Run Code Online (Sandbox Code Playgroud)
SELECT TOP 5
ChangeDate,
dbo.ToDateTimeOffset(ChangeDate) AS ChangeDateOffset
FROM AuditLog
Run Code Online (Sandbox Code Playgroud)
返回所需的:
ChangeDate ChangeDateOffset
======================= ==================================
2013-07-25 04:00:03.060 2013-07-25 04:00:03.0600000 -04:00
2013-07-24 04:00:03.073 2013-07-24 04:00:03.0730000 -04:00
2013-07-23 04:00:03.273 2013-07-23 04:00:03.2730000 -04:00
2013-07-20 04:00:02.870 2013-07-20 04:00:02.8700000 -04:00
2013-07-19 04:00:03.780 2013-07-19 04:00:03.7800000 -04:00
Run Code Online (Sandbox Code Playgroud)
如果内置函数只是这样做,那将是理想的:
TODATETIMEOFFSET(value)
Run Code Online (Sandbox Code Playgroud)
而不是必须创建一个"过载":
dbo.ToDateTimeOffset(value)
Run Code Online (Sandbox Code Playgroud)
注意:任何代码都将发布到公共域中.无需归属.
| 归档时间: |
|
| 查看次数: |
40203 次 |
| 最近记录: |