如何将 Sql Server 2008 DateTimeOffset 转换为 DateTime

Posted

技术标签:

【中文标题】如何将 Sql Server 2008 DateTimeOffset 转换为 DateTime【英文标题】:How can I convert a Sql Server 2008 DateTimeOffset to a DateTime 【发布时间】:2011-06-24 15:28:33 【问题描述】:

我希望将具有DATETIMEOFFSET 字段的表转换为DATETIME 字段但通过注意偏移量来重新计算时间。实际上,这会将值转换为 UTC

例如。

CreatedOn: 2008-12-19 17:30:09.0000000 +11:00

这将被转换为

CreatedOn: 2008-12-19 06:30:09.0000000

CreatedOn: 2008-12-19 06:30:09.0000000 + 00:00 -- that's a `DATETIMEOFFSET`, but `UTC`.

干杯:)

【问题讨论】:

参考***.com/questions/39719645/… 【参考方案1】:

使用几乎任何样式进行转换都会导致 datetime2 值转换为 UTC。 此外,从 datetime2 转换为 datetimeoffset 只需将偏移量设置为+00:00,如下所示,因此这是从Datetimeoffset(offset!=0) 转换为Datetimeoffset(+00:00) 的快速方法

declare @createdon datetimeoffset
set @createdon = '2008-12-19 17:30:09.1234567 +11:00'

select CONVERT(datetime2, @createdon, 1)
--Output: 2008-12-19 06:30:09.12

select convert(datetimeoffset,CONVERT(datetime2, @createdon, 1))
--Output: 2008-12-19 06:30:09.1234567 +00:00

【讨论】:

有人能解释一下CONVERT的最后一个参数“1”是什么意思吗?此参数的所有示例都使用字符类型作为输出或输入类型。这里我们将 datetimeoffset 转换为 datetime。 convert() 函数采用第三个参数,该参数指定输出的格式。 https://www.w3schools.com/sql/func_convert.asp。 1 = "mm/dd/yy" 格式 第三个参数对于从datetimeoffsetdatetime2 的转换没有任何意义。它用于varchar 转换。 docs.microsoft.com/en-us/sql/t-sql/functions/…(也是 W3Schools?现在有这么多更好的选择!) @OzBob 你一定误解了这个问题,请求的两个选项之一是删除偏移量。关键是将时间转换为UTC。是否保持 +00.00 既不存在也不存在 请注意下面@user166390 的答案。 “如果未指定样式,则转换时丢弃时区信息”。如果不指定第三个参数,无论是 1 还是其他,都会丢失正确的 UTC 转换【参考方案2】:

我会使用内置 SQL 选项:

select SWITCHOFFSET(cast('2008-12-19 17:30:09.0000000 +11:00' as datetimeoffset),'+00:00')

【讨论】:

这是最好的答案(也支持 sql server 2014)。使用SWITCHOFFSET(...,0)内置函数转换datetimeoffset简单干净。【参考方案3】:

我知道这是一个老问题,但是,如果您想将 DateTimeOffset 转换为 DateTime,我认为您需要考虑要转换的服务器的时区。如果你只是做一个 CONVERT(datetime, @MyDate, 1) 你只会丢失时区,这可能会导致错误的转换。

我认为你首先需要切换 DateTimeOffset 值的偏移量,然后进行转换。

DECLARE @MyDate DATETIMEOFFSET = '2013-11-21 00:00:00.0000000 -00:00';
SELECT CONVERT(DATETIME, SWITCHOFFSET(@MyDate, DATEPART(tz,SYSDATETIMEOFFSET())));

在偏移量为 -7:00 的服务器上将 '2013-11-21 00:00:00.0000000 -00:00' 转换为 DateTime 的结果将是 2013-11-20 17:00:00.000。上面的逻辑不管服务器的时区是什么,也不管DateTime值的偏移量,都会转换成服务器时区的DateTime。

我认为您需要这样做,因为 DateTime 值包含该值在服务器时区中的假设。

【讨论】:

感谢 - 我们现在在 Azure 中运行了更多代码,但查询本地数据库,很高兴能够在云中获取 DateTimeOffset,通常是 UTC,然后转换它到本地时间,而不必知道本地服务器时区。如果云不是 UTC,在云中使用 DateTimeOffset 也会使我们隔离。 @Jeremy 显然,您在 5 年前还没有测试过答案中的代码。您不需要考虑要转换的服务器上的时区。 0600+04:00 在任何时区总是转换为 0200 (UTC)。 p/s 日期时间值是您的解释。它根本没有时区假设,这就是 datetimeoffset 存在的原因。 @RichardTheKiwi 我不认为你理解他在做什么。假设@MyDate 是外部数据。假设数据库将该值存储为带有服务器本地时间的datetime(对于仅在一个时区运行的应用程序来说,这是一种非常常见的应用程序规则)。您需要更正时区之前datetimeoffset 转换它。 SELECT CONVERT(DATETIME, @MyDate) 在 2013 年 11 月 21 日返回午夜,无论服务器的时区如何,也不管 datetimeoffset 中指定的偏移量如何。它只是删除偏移量而不转换为本地时间。【参考方案4】:

SQL Server 中的 DateTimeoffset(时区)转换。

SQL Server 2016 (13.x) 及更高版本

示例

Select GETUTCDATE()
Select Convert(DATETIME, GETUTCDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Central European Standard Time')
Select Convert(DATETIME, GETUTCDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time')

结果将是

2020-08-18 08:22:21.640
2020-08-18 10:22:21.640
2020-08-18 13:52:21.640

【讨论】:

这就是我要找的。我需要将时区偏移保留到最终的日期时间值中,而不是丢弃。在另一个答案中键入 126 返回错误。谢谢! 正是我要找的,我需要时间来转换成主要时间块,这应该是最高投票的答案!!【参考方案5】:

注意:如果未指定样式(此处为“126”),则转换时丢弃时区信息。它也可能在其他一些样式中被丢弃,我不知道——无论如何,以下正确调整了 TZ 信息。见CAST and CONVERT。

select convert(datetime, cast('2008-12-19 17:30:09.0000000 +11:00' as datetimeoffset), 126) as utc;

快乐的 SQL'ing。

编辑

不确定这是否重要,但...datetime 实际上无法存储该级别的精度/准确度。如果上述运行,小数秒将被截断为 3 位数字(并且精度低于该数字)。与datetime2(和datetimeoffset(7))相同,会产生非截断值:

select convert(datetime2, cast('2008-12-19 17:30:09.1234567 +11:00' as datetimeoffset(7)), 126) as utc;

【讨论】:

什么是样式 126?为什么是 126? @Pure.Krome 请参阅回复中指向 CAST 和 CONVERT 的链接。 126 因为我喜欢 ISO 8601 并且不得不选择一个。这实际上与网络维基选择 1 没有什么不同。如前所述(在两个答案中),某些样式可能不考虑 TZ。 SQL Server 2008 R2 中的快速测试表明,仅使用样式 0 或(等效地)省略样式代码会丢弃时区信息。 MSDN 文档中列出的任何其他代码都将保留它。 我发现在直接从 DATETIMEOFFSET 转换为 DATETIME2 时,尝试样式 126 会导致错误(在 SQL Server 2012 中)作为不受支持的样式。除了 0 和 1 之外,我没有发现任何其他被接受的(但我没有尝试所有这些)。 126 是将DATETIMEOFFSET 转换为VARCHAR 的有效样式。【参考方案6】:

为了考虑夏令时,我使用了以下内容:

CONVERT(
  DateTime, 
  SWITCHOFFSET(
    CONVERT(
      DateTimeOffset, 
      CONVERT(
        DateTime, 
        [time_stamp_end_of_interval], 
        120
      )
    ),
    DATENAME(
      TzOffset, 
      CONVERT(
        DateTime, 
        [time_stamp_end_of_interval], 
        120
      ) AT TIME ZONE 'Pacific Standard Time'
    )
  )
)
AS GOOD_PST

注意:time_stamp_end_of_interval 是一个 varchar

【讨论】:

仅使用 SWITCHOFFSET(..., 0) 将 datetimeoffset 转换为 utc 没有与夏令时相关的问题。见docs.microsoft.com/en-us/sql/t-sql/functions/…

以上是关于如何将 Sql Server 2008 DateTimeOffset 转换为 DateTime的主要内容,如果未能解决你的问题,请参考以下文章

将 SQL Server 2008 r2 降级到 SQL Server 2008

如何将架构绑定添加到 SQL Server 2008 中的视图

如何将 Sql Server 2008 DateTimeOffset 转换为 DateTime

如何将excel数据加载到sql server 2008表中?

如何设置将SQL SERVER2012数据库备份还原到SQL SERVER2008上

如何将数据库sql server2008中的数据库生成脚本输出