Преобразование из глобализированного формата даты / времени (возможно, ISO8601) в тип даты и времени SQL Server - PullRequest
0 голосов
/ 26 июня 2009

Существует ли строковый формат для представления даты и времени, который SQL сможет проанализировать и преобразовать в другое смещение (например, EST -> UTC).

У меня есть строка от пользователя, такая как:

declare @p1 varchar(50);
declare @utcDateTime datetime;

set @p1 = "2009-06-26 14:30:00.000Z-4:00";   -- could be ISO8601

-- what do I do here to convert @p1?

set @utcDateTime = -- should be "2009-06-26 18:30:00.000"

Я хочу иметь возможность преобразовать строку в эквивалент UTC и сохранить ее в поле даты и времени. Такой что:

select @ utcDateTime 

должно дать это:

"2009-06-26 18:30:00.000"

Другими словами, я хочу сохранить дату и время со значением '2009-06-26 18:30' с учетом первой строки.

Кроме того, мы должны предположить, что сервер находится не в том же часовом поясе, что и пользователь (поэтому мы не можем просто определить дату смещения (gettime (), getutctime ()).

Я пытался использовать convert (...) и cast (... как datetime), но безуспешно.

Есть ли способ сделать это в SQL Server 2005?

Ответы [ 2 ]

4 голосов
/ 26 июня 2009

Хорошо, вот моя попытка - это было весело: -)

 DECLARE  @datestr varchar(100)

SET @datestr = '2009-06-26 14:30:00.000Z+4:00'

SELECT @datestr, DATEADD(mi, -1 * CAST(SUBSTRING(@datestr,25,1)+'1' AS int) *  
    DATEDIFF(mi,'1900-01-01', CAST(SUBSTRING(@datestr,26,5) as datetime)),   
    CAST(LEFT(@datestr,23) as datetime) )

SET @datestr = '2009-06-26 14:30:00.000Z-4:00'

SELECT @datestr, DATEADD(mi, -1 * CAST(SUBSTRING(@datestr,25,1)+'1' AS int) *  
    DATEDIFF(mi,'1900-01-01', CAST(SUBSTRING(@datestr,26,5) as datetime)),   
    CAST(LEFT(@datestr,23) as datetime) )

SET @datestr = '2009-06-26 14:30:00.000Z+14:00'

SELECT @datestr, DATEADD(mi, -1 * CAST(SUBSTRING(@datestr,25,1)+'1' AS int) *  
    DATEDIFF(mi,'1900-01-01', CAST(SUBSTRING(@datestr,26,5) as datetime)),   
    CAST(LEFT(@datestr,23) as datetime) )

SET @datestr = '2009-06-26 14:30:00.000Z+4:30'

SELECT @datestr, DATEADD(mi, -1 * CAST(SUBSTRING(@datestr,25,1)+'1' AS int) *  
    DATEDIFF(mi,'1900-01-01', CAST(SUBSTRING(@datestr,26,5) as datetime)),   
    CAST(LEFT(@datestr,23) as datetime) )

SET @datestr = '2009-06-26 14:30:00.000Z-4:30'

SELECT @datestr, DATEADD(mi, -1 * CAST(SUBSTRING(@datestr,25,1)+'1' AS int) *  
    DATEDIFF(mi,'1900-01-01', CAST(SUBSTRING(@datestr,26,5) as datetime)),   
    CAST(LEFT(@datestr,23) as datetime) )

SET @datestr = '2009-06-26 14:30:00.000Z+14:30'

SELECT @datestr, DATEADD(mi, -1 * CAST(SUBSTRING(@datestr,25,1)+'1' AS int) *  
    DATEDIFF(mi,'1900-01-01', CAST(SUBSTRING(@datestr,26,5) as datetime)),   
    CAST(LEFT(@datestr,23) as datetime) )

Возвращает:

2009-06-26 14:30:00.000Z+4:00  2009-06-26 10:30:00.000

2009-06-26 14:30:00.000Z-4:00  2009-06-26 18:30:00.000

2009-06-26 14:30:00.000Z+14:00 2009-06-26 00:30:00.000

2009-06-26 14:30:00.000Z+4:30  2009-06-26 10:00:00.000

2009-06-26 14:30:00.000Z-4:30  2009-06-26 19:00:00.000

2009-06-26 14:30:00.000Z+14:30 2009-06-26 00:00:00.000
1 голос
/ 26 июня 2009

в одну сторону, если вы используете datetime запустите это в окне

declare @date varchar(100)
select @date = '2009-06-26 14:30:00.000'

select dateadd(hh,datediff(hh,getdate(),getutcdate()),@date)

Выход 2009-06-26 18: 30: 00.000

лучше просто использовать getutcdate () все время и сохранять смещение пользователей в своем профиле

SQL Server 2008 имеет новый datetimeoffset тип данных, который делает это намного проще

Теперь вот ответ, который будет работать с вашими данными (я также добавил код 1/2 часа)

Как работает код, объясняется здесь: Добавление смещений времени, переданных в datetime, для генерации локализованного datetime

    declare @date varchar(100),@multiplier int

select @date = '2009-06-26 14:30:00.000Z+4:30'
select @multiplier = case when @date like '%+%' then -1 else 1 end


select dateadd(mi, @multiplier *convert(int,right(@date,2)),dateadd(hh
    ,-1 * convert(int,replace(substring(@date,patindex('%z%',@date)+ 1,3),':',''))
    ,left(@date,23)))
go


--2009-06-26 10:00:00.000

declare @date varchar(100),@multiplier int

select @date = '2009-06-26 14:30:00.000Z-4:30'
select @multiplier = case when @date like '%+%' then -1 else 1 end

select dateadd(mi, @multiplier *convert(int,right(@date,2)),dateadd(hh
    ,-1 * convert(int,replace(substring(@date,patindex('%z%',@date)+ 1,3),':',''))
    ,left(@date,23)))
go

--2009-06-26 19:00:00.000

declare @date varchar(100),@multiplier int

select @date = '2009-06-26 14:30:00.000Z+14:30'
select @multiplier = case when @date like '%+%' then -1 else 1 end

select dateadd(mi, @multiplier *convert(int,right(@date,2)),dateadd(hh
    ,-1 * convert(int,replace(substring(@date,patindex('%z%',@date)+ 1,3),':',''))
    ,left(@date,23)))
go

--2009-06-26 01:00:00.000


declare @date varchar(100),@multiplier int
select @date = '2009-06-26 14:30:00.000Z-14:30'
select @multiplier = case when @date like '%+%' then -1 else 1 end

select dateadd(mi, @multiplier *convert(int,right(@date,2)),dateadd(hh
    ,-1 * convert(int,replace(substring(@date,patindex('%z%',@date)+ 1,3),':',''))
    ,left(@date,23)))
go

--2009-06-27 05:00:00.000
...