在我的表中,我有一个包含日期的列,如下所示:
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时间之间返回不同的时间我的问题解决了。
我希望你能理解我的问题。
答案 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