0

在过去一天左右的时间里,我一直在为此烦恼,我希望这里的人可以提供一些启示。

我最近迁移到了 UTC 格式的 Amazon RDS SQL Server。但是,我在数据库中的所有时间都在当地时区(西欧)。我的下一个挑战是将所有这些 DateTimes 转换为 UTC。

我认为,最快的方法是直接在 Sql Server 中执行此操作,但是,因为没有简单的方法来解释 DST,所以我求助于 SQL CLR 中的用户定义函数(从此处的另一个答案中看到),它没有暂时不工作。它现在看起来像这样:

[Microsoft.SqlServer.Server.SqlFunction]
  public static SqlDateTime ToUniversal(SqlDateTime dt)
  {
    if (dt.IsNull)
    {
      return SqlDateTime.Null;
    }
    else
    {
      return dt.Value.ToUniversalTime();
    }
  }

但是,该函数不会从本地时间转换为世界时间。例子,

select creationtime, dbo.ToUnversal(CreationTime) as New from testtable

返回相同的两个日期时间,它们也是原始日期时间。

这是为什么?是不是因为 Sql Server 已经在 UTC 中,所以它识别出来并且没有进一步转换它?

此外,如果您有任何其他推荐的方法,请添加它们。我已经尝试用一个小 .NET 应用程序解决这个问题,但是我的 120GB 数据库非常慢。

4

1 回答 1

1

比赛有点晚了,但是哦,好吧..

请记住,如果您采用这种 .NET 方式,如果源和目标设置为不同的(系统)时区,则必须在源服务器上进行转换!.NET 在执行机器上使用 Windows 上设置的时区。

IIRC,来自 SQL 的 DateTimes 将通过 DateTimeKind.Unspecified 提供给 .NET。如果是这种情况, DateTime.ToUniversalTime 总是假定您给它一个本地时间并且应该转换得很好。

但是,如果系统时区与源服务器时区匹配——不是 UTC——并且如果 DateTimes 错误地返回 DateTimeKind.Universal 所以 ToUniversal 什么都不做,你可以强制 DateTimes 通过执行以下操作进行转换:

  [Microsoft.SqlServer.Server.SqlFunction]
  public static SqlDateTime ToUniversal(SqlDateTime dt)
  {
    if (dt.IsNull)
    {
      return SqlDateTime.Null;
    }
    else
    {
      // SpecifyKind changes the Kind property without changing the actual
      var tempDate = DateTime.SpecifyKind(dt.Value, DateTimeKind.Local);
      return tempDate.ToUniversalTime();
    }
  }
于 2016-01-25T11:45:38.920 回答