2012-04-24 168 views
3

我有一个DateTime varchar,格式为:2005-08-08T00:00:00 + 01:00。如何将DateTime字符串转换为SQL Server中的DateTime

  1. 此格式是否有名称? (它不是ISO8601,它是RFC3339吗?)
  2. 如何使用Transact-Sql将其转换为DateTime?

编辑 以下是简要的答案,从别人输入拼凑起来:

  1. ISO8601与UTC的时差。如果是UTC,它将以'Z'而不是'+01:00'结束。 wikipedia
  2. 可以按如下方式将其转换为本地时间或UTC:

    DECLARE @d VARCHAR(25)SET @d = '2007-08-08T00:01:00 + 01:00' SET @d = '2007-08-08T00:01:00-01:00'SET @d ='2007-08-08T00:01:00 + 05:30'

    SELECT @d as Input,CONVERT (DATETIME,LEFT(@d,19),126)AS LocalDate ,DATEADD(MINUTE,-CAST((SUBSTRING(@d,20,1)+ RIGHT(@d,2))INT INT),DATEADD HOUR ,-CAST(SUBSTRING(@d,20,3)AS INT) ,CONVERT(DAT ETIME,LEFT(@d,19),126)))作为UtcDate WHERE @d LIKE '_ - - _T__: [+ - ] '

结果:

Input      LocalDate    UtcDate 
------------------------- ----------------------- ----------------------- 
2007-08-08T00:01:00+01:00 2007-08-08 00:01:00.000 2007-08-07 23:01:00.000 

2007-08-08T00:01:00-01:00 2007-08-08 00:01:00.000 2007-08-08 01:01:00.000 

2007-08-08T00:01:00+05:30 2007-08-08 00:01:00.000 2007-08-07 18:31:00.000 
+1

请查看此页面 - > http://www.sqlusa.com/bestpractices/datetimeconversion/ – rt2800 2012-04-24 15:07:34

+0

是的,我发现该网页使用谷歌。虽然在那里找不到我的格式。 – Colin 2012-04-24 15:32:29

+0

值得注意的一件事是,您的SUBSTRING()语句会删除时区的分钟组件,这意味着它在相对于UTC不是整个小时的时区中会不正确。例如印度是UTC + 5:30。 – Rory 2012-08-22 09:29:50

回答

8

在SQL Server中您可以使用datetimeoffset数据类型。

SELECT [Result] = CONVERT(datetimeoffset, '2005-08-08T00:01:00+01:00', 127) 

输出:

Result 
---------------------------------- 
2005-08-08 00:01:00.0000000 +01:00 

在SQL Server 2005 早期就可以计算UTC日期和偏移:

SELECT [LocalDate], [OffsetMinutes], [UtcDate] 
FROM 
(
    SELECT [IsoDate] = '2007-08-08T00:01:00+01:00' 
) A 
OUTER APPLY 
(
    SELECT [LocalDate] = CONVERT(datetime, LEFT([IsoDate], 19), 126) 
    , [OffsetMinutes] = 
     CASE SUBSTRING([IsoDate], 20, 1) 
      WHEN '+' THEN +1 
      WHEN '-' THEN -1 
     END 
     * DATEDIFF(minute, 0, 
      CAST(SUBSTRING([IsoDate], 21, 5) + ':00' AS datetime)) 
    WHERE [IsoDate] LIKE '____-__-__T__:__:__[+-]__:__' 
) B 
OUTER APPLY 
(
    SELECT [UtcDate] = DATEADD(minute, -[OffsetMinutes], [LocalDate]) 
) C 

输出:

LocalDate    OffsetMinutes UtcDate 
----------------------- ------------- ----------------------- 
2007-08-08 00:01:00.000 60   2007-08-07 23:01:00.000 
+0

谢谢,但数据库是Sql Server 2005,我需要将它转换为DateTime – Colin 2012-04-24 15:24:43

+0

当然, 你是对的。我无法将字符串中的所有信息直接转换为DateTime。时区必须存储在别处(如果需要) – Colin 2012-04-24 15:55:54

+0

好的。我已经添加了SQL Server 2005的解决方案 – 2012-04-24 21:26:11

1

它ISO8601随着时间区间Z

使用

SELECT CONVERT(datetime,'2005-08-08T00:00:00',126) 

看到 MSDN Explanation

编辑: 我认为这事与我原先设想的TSQL将接受最终的区域做,但不会原来它。

+0

刚刚在sql server 2005中进行了测试,并且2008失败 – Taryn 2012-04-24 15:10:12

+0

考虑到'SELECT CONVERT(date,'2005-08-08T00:00:00 + 01:00',127)确实有效, – AbstractChaos 2012-04-24 15:12:47

+0

发生变化仍在检查区域不工作的原因 – AbstractChaos 2012-04-24 15:15:04

2

你可以这样做一个真正丑陋的方式,在你第一次得到的日期,然后得到的时间,并添加为小时的偏差:

declare @d varchar(50) 
set @d = '2005-08-08T00:00:00+01:00' 

select Convert(datetime, left(@d, 10)) 
    + DateAdd(hour, Cast(substring(@d, 21, 2) as int), convert(datetime, substring(@d, 12, 8))) 

或综合版本:

SELECT DateAdd(hour, Cast(substring(@d, 21, 2) as int), CONVERT(datetime, LEFT(@d, 19) ,127)) 

Final Result: 
2005-08-08 01:00:00.000 

如果你不需要偏移量,那么:

declare @d varchar(50) 
set @d = '2005-08-08T00:00:00+01:00' 

select Convert(datetime, left(@d, 10)) 
    + convert(datetime, substring(@d, 12, 8)) 

Result: 
2005-08-08 00:00:00.000 
+0

想想这个,以及Anthony Faull的回答。该字符串包含日期时间和时区,但Sql Server 2005只能存储DateTime。因此,我必须放弃时区,或将其转换为我已决定将日期时间存储在(GMT) – Colin 2012-04-24 15:43:18

+0

中的时区并且这是更简洁的方式:SELECT DateAdd(hour,Cast(substring(@d,21 ,2)如int),CONVERT(datetime,LEFT(@d,19),127))。我建议你编辑你的答案... – Colin 2012-04-24 15:49:41

+0

@Colin我更新了我的答案与编辑。 – Taryn 2012-04-24 19:13:34

0

根据选定的答案,datetimeoffset是一个很好的解决方案。但是,要小心SQL Server端的内置函数。 (我试图复制粘贴此为接受的答案评论,但它不会格式化代码示例)

select GETDATE(), CONVERT(datetimeoffset, GETDATE(), 127), CONVERT(varchar, convert(datetimeoffset, getdate(), 127)) 
-- Ugg! a SQL Server Bug!!! 
-- 2013-08-16 12:54:54.090 2013-08-16 12:54:54.0900000 +00:00 2013-08-16 12:54:54.0900000 +0 

select GETUTCDATE(),convert(datetimeoffset, GETUTCDATE(), 127), convert(varchar, convert(datetimeoffset, GETUTCDATE(), 127)) 
-- 2013-08-16 16:54:54.090 2013-08-16 16:54:54.0900000 +00:00 2013-08-16 16:54:54.0900000 +0 
+0

如果你演示的问题是当你转换为varchar时字符串被截断,那是因为你没有指定varchar和sql server的默认长度为30个字符。 http://msdn.microsoft.com/en-us/library/ms176089.aspx – Colin 2013-08-18 10:37:25

+0

实际上,我试图演示的是,使用datetimeoffset转换的GETDATE()应用00:00而不是正确的时区格式。您可以在GETDATE()和GETUTCDATE()之间使用datediff并手动生成字符串,但有人会认为SQL Server在使用模式127转换时将在转换中正确处理偏移量。 – Jim 2013-08-19 12:20:22

+0

Sql服务器无法推断从datetime转换为datetimeoffset,因为该信息未存储在datetime结构中。您需要SYSDATETIMEOFFSET()函数。请参阅http://stackoverflow.com/a/8634229/150342 – Colin 2013-08-19 13:12:06