将日期以毫秒为单位转换为日期

时间:2015-10-01 09:09:29

标签: sql-server sql-server-2008 date datetime

在我的表中,我有一个包含日期的列,如下所示:

table a 
      dateinmili
      1440301846096 //first six month date 
      1443589721039 //second six month date

我将它用于我的Android设备,它运行正常。当我想在SQL Server的PROCEDURE中使用这段时间并将此时间转换为人类时间(人类可以理解)和日期时我遇到了问题。

我在伊朗使用UTC时间的前六个波斯日期月份4.30和3.30,在第二个六个月。

对于PROCEDURE中的转换日期,我使用以下代码:

CONVERT(nVARCHAR(10),DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), DATEADD(ss,dateinmili/1000,'1970-01-01')),8) as date 
DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), DATEADD(ss,dateinmili/1000,'1970-01-01')) as time

,这是我的问题:

当我在第二个六个月转换日期和在一年中的前六个月注册的日期时,我在实时和转换时间之间得到1小时的差异。我知道那是因为

 DATEDIFF(mi, GETUTCDATE(), GETDATE())    

在UTC时间和本地时间之间返回不同的方法(在我的例子中返回3:30而不是4:30),但我不知道如何解决这个问题?

我可以添加包含当前UTC时间的列,但我正在寻找另一种方式。

更新

我看到this question并且它不是我长期转换的问题 我的问题在于我的国家UTC时间在一年中不是恒定的,而是在3.30和4.30之间变化,例如我在前六个月(波斯语六个月)注册的日期如1440271800000并且现在转换它我们在第二个六个月(波斯六个月)并使用此代码进行转换。

declare @unixTS bigint
set @unixTS = 1440271800000

select dateadd(ms, @unixTS%(3600*24*1000), 
    dateadd(day, @unixTS/(3600*24*1000), '1970-01-01 03:30:00.0')
)

我明白了

 2015-08-22 23:00:00.000     

但它不是正确的日期;正确的日期是:

2015-08-23 00:00:00.000

因为当时注册UTC的时间是4.30而不是3.30,但知道我何时转换 它的UTC是3.30。

我希望SQL中有一个返回UTC时间不同的方法;我的意思是给它一个日期,并在当地时间和gmt时间之间返回不同的时间我的问题解决了。

我希望你能理解我的问题。

1 个答案:

答案 0 :(得分:0)

在美国,夏季我们有夏令时,在大多数地区,这意味着我们也没有固定偏离UTC。较早版本的MS Dynamics CRM用于保存UTC中的所有内容,因此当我们想要在当地时间导出数据时,我们进行了类似的练习。我创建了一组SQL函数,这些函数将采用标准GMT偏移量和我想要转换的日期时间,并确定是否应用标准或DST偏移量并返回本地日期时间。如果您的偏移量遵循一组规则,那么您可以修改它:

    CREATE function [dbo].[DC_GMTtoLocal]
    (@OrigGMT datetime, 
@StandardOffset int)
RETURNS datetime
AS
BEGIN
DECLARE @RevDate datetime

set @RevDate = CASE dbo.DC_DaylightSavingTime_IsInEffect(@OrigGMT)
    WHEN 1 THEN DATEADD(hour, - @StandardOffset + 1, @OrigGMT) --  in DST
    ELSE DATEADD(hour, - @StandardOffset, @OrigGMT) -- Not In DST
    END

return @RevDate 
END


GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE function [dbo].[DC_DaylightSavingTime_IsInEffect]
(@DtTime datetime)
RETURNS tinyint
AS
BEGIN
DECLARE @DLSStart datetime
, @DLSEnd datetime
, @DLSActive tinyint

SET @DLSActive = 0
If DATEADD(YEAR,3,GETDATE()) > @DtTime 
BEGIN
    SET @DLSStart =(SELECT dbo.DC_GetDaylightSavingsTimeStart(CONVERT(varchar,DATEPART(YEAR,@DtTime))))
    SET @DLSEnd =(SELECT dbo.DC_GetDaylightSavingsTimeEnd(CONVERT(varchar,DATEPART(YEAR,@DtTime))))


    IF @DtTime BETWEEN @DLSStart AND @DLSEnd 
    BEGIN
        SET @DLSActive = 1 
    END
        --SET @DLSActive = 0
END

RETURN @DLSActive 
END

GO

CREATE function [dbo].[DC_GetDaylightSavingsTimeStart]
(@Year varchar(4))
RETURNS smalldatetime
as
--Start date: We evaluate the day of the week corresponding to the first day of the month and find the second Sunday of March using a Case statement 
begin
declare @DTSStartWeek smalldatetime, @DTSEndWeek smalldatetime
set @DTSStartWeek = '03/01/' + convert(varchar,@Year)
return case datepart(dw,@DTSStartWeek)
when 1 then 
dateadd(hour,170,@DTSStartWeek)
when 2 then
dateadd(hour,314,@DTSStartWeek)
when 3 then 
dateadd(hour,290,@DTSStartWeek)
when 4 then 
dateadd(hour,266,@DTSStartWeek)
when 5 then 
dateadd(hour,242,@DTSStartWeek)
when 6 then 
dateadd(hour,218,@DTSStartWeek)
when 7 then
dateadd(hour,194,@DTSStartWeek)
end
end


GO

CREATE function [dbo].[DC_GetDaylightSavingsTimeEnd]
(@Year varchar(4))
RETURNS smalldatetime
as
-- End date: We evaluate the day of the week corresponding to the first day of the month and find the first Sunday of March using a Case statement 
begin
declare @DTSEndWeek smalldatetime
set @DTSEndWeek = '11/01/' + convert(varchar,@Year)
return case datepart(dw,dateadd(week,1,@DTSEndWeek))
when 1 then
dateadd(hour,2,@DTSEndWeek)
when 2 then
dateadd(hour,146,@DTSEndWeek)
when 3 then
dateadd(hour,122,@DTSEndWeek)
when 4 then
dateadd(hour,98,@DTSEndWeek)
when 5 then 
dateadd(hour,74,@DTSEndWeek)
when 6 then 
dateadd(hour,50,@DTSEndWeek)
when 7 then 
dateadd(hour,26,@DTSEndWeek)
end
end


GO