我的应用程序需要收集全球所有地点的“星期二”购买,其中“Tueday”是该地点的星期二(不论时区)。如果用户需要在下周重新运行报告,我还需要获得“上周二”的数据。我们所有的数据都是使用DateTimeOffset存储的。
所以 9/4/12 00:00:00 -7至9/4/12 23:59:59 -7 必须匹配 9/4/12 00:00:00 +11到9/4/12 23:59:59 +11 当我执行我的WHERE子句时。
我无法在WHERE子句中转换为UTC,因为这将获取伦敦“星期二”的数据(取决于DST),而不是位置的星期二。
我尝试从DateTimeOffset转换为DateTime,但似乎转换为UTC。 (在我的测试中,通过9/1/12至9/30/12获取了8/31/12数据。)
使用TSQL做这样的事情是否有诀窍?
谢谢!
答案 0 :(得分:2)
恕我直言
DateTimeOffset = DateTime + Offset(来自UTC)
因此,您的数据已经代表客户的本地日期和时间。只需将其转换为DateTime,您将获得客户端的本地日期和时间。
但是如果您想将Offset添加到日期时间并希望得到Datetime那么
DECLARE @PurchaseDate DATETIMEOFFSET(7) = CAST('2007-05-08 12:30:29.1234567 +5:00' AS datetimeoffset(7))
SELECT CAST(SWITCHOFFSET (@PurchaseDate , '+00:00') AS DATETIME)
请查看此博客以获取更多信息。
http://blogs.msdn.com/b/bartd/archive/2009/03/31/the-death-of-datetime.aspx
答案 1 :(得分:1)
将DATETIMEOFFSET
转换为DATETIME
时,它会将日期和时间视为值中的偏移量,并简单地删除时区。在转换为DATE
或TIME
时也是如此。因此,我认为您可以简单地将列转换为DATE
,并将其与您希望匹配的仅限日期的值进行比较:
DECLARE @targetDate DATETIME2 = '2012-09-04' --Or we could use DATE here
SELECT [PurchaseId], [PurchaseTime], CAST([PurchaseTime] AS DATE) AS "PurchaseDate"
FROM [Purchases]
WHERE CAST([PurchaseTime] AS DATE) = @targetDate
我不确定这会有多高效(如果提供商真的很聪明,希望也不错 - 可能是哪个SQL Server),但你也可以通过限制原始列值来改进它:
DECLARE @targetDate DATETIME2 = '2012-09-04' --DATETIME2 so we can adjust by hours
SELECT [PurchaseId], [PurchaseTime], CAST([PurchaseTime] AS DATE) AS "PurchaseDate"
FROM [Purchases]
WHERE CAST([PurchaseTime] AS DATE) = @targetDate --Keep only the local-date matches
AND [PurchaseTime] >= DATEADD(hh, -14, @targetDate) --Up to 14-hour time zone offset
AND [PurchaseTime] <= DATEADD(hh, 38, @targetDate) --24 hours later plus 14
这应该有效地索引到一组可能性,然后在转换到本地日期时正确过滤。请注意,时区偏移最长可达14小时(新西兰距离我们最远的时间为+13:00,但根据MSDN可以到+/- 14:00),@ targetDate将在一天的开始,所以它比较早回到14小时和24 + 14 = 38小时后。 DATETIME2与DATETIMEOFFSET具有相同的范围和精度,因此它比原始的DATETIME更好(但它也可以用DATETIME工作)。