如何从SQL Server中获取DateTime数据而忽略时区问题?

时间:2012-12-05 14:54:33

标签: c# sql-server datetime timezone

我的情况是我们将数据存储在SQL Server数据库中,支持2005年。存储DateTime值时,它位于客户端的本地时间。我需要能够在任何地方的任何其他客户端上获取该日期,而不考虑其他客户可能处于的任何时区。

例如,当纽约的用户输入DateTime值“2012-12-20 00:00”时,我希望加利福尼亚的用户看到相同的DateTime值。这些DateTime值不应该尊重时区的差异,但这就是我看到的情况。目前,SQL Server将该DateTime作为“2012-12-19 21:00”提供给California用户。请注意,由于从EST到PST的变化导致-3小时回滚,所以现在是前一天(为此对话而忘记DST问题)。

逐字逐句地获取数据,而不是按时区翻译,这是我需要完成的。那么你能提供什么建议?

需要考虑的一些代码:

这是表格:

CREATE TABLE [dbo].[tblMeterReadings](
[fldMeterReadingsID] [int] IDENTITY(1,1) NOT NULL,
[fldMeterID] [int] NOT NULL,
[fldUser] [varchar](50) NULL,
[fldBy] [varchar](50) NULL,
[fldDateOfReading] [datetime] NULL,
[fldReading] [float] NULL,
[fldIsArchived] [bit] NULL DEFAULT ((0)),

我们有一个可以完成工作的Sql类,在下面的例子中,“sql”是该类的一个对象。使用参数化查询进行调用,其中@ data0是要存储在SQL DateTime字段中的DateTime对象:

sql.Execute(@"INSERT INTO tblMeterReadings (fldMeterID, fldDateOfReading) VALUES (" + MeterID + ", @data0)", Date);

最终,这将设置一个SqlCommand,分配参数,并触发command.ExecuteNonQuery()调用。

现在,要检索日期,我只需将其选入DataTable(再次使用我们的Sql类助手):

DataTable myTable = sql.readDataTable(@"SELECT fldMeterID, fldDateOfReading FROM tblMeterReadings");

所以我看到的是,在数据库本身,日期是“2012-12-20 00:00”,正如我所料,但是当我在调试中检查myTable内容时,我看到该表中的日期是“2012-12-19 21:00”。

数据库是在运行状态为EST的计算机上运行的SQL Server上创建的。但是,我的机器设置为PST。因此,在SELECT中将DateTime值传递给我的方式不同。

我错过了什么?

3 个答案:

答案 0 :(得分:2)

将UTC日期存储在数据库中。只在客户端显示时将其转换为本地时间。

服务器端,使用getutcdate()代替getdate()

答案 1 :(得分:2)

感谢您的好意,并根据您的建议进行了一些研究,我们已经解决了我们的问题。

特别感谢ebyrob提供的帮助和此链接:http://support.microsoft.com/kb/842545

最终证明这种联系是银弹。

基本问题是,当您构造DataTable或DataSet时,有关其创建时区的信息将使用它进行编码。然后,如果您通过连接将该对象传递给位于不同时区内的计算机,则其中的任何DateTime值将根据时区的差异进行调整。

根据这种理解,修复方法是将所有DateTime DataColumns的DateTimeMode属性设置为DataSetDateTime.Unspecified。这样可以防止序列化后的日期调整,而是逐字递送DateTime值。

我还想指出文章指定了DataSet,但我们已经证明DataTable也很脆弱。事实上,我很确定它归结为DataColumn本身(那些具有DateTime类型的那些)。我认为这篇文章也说明了这一点。

再次感谢;我想我们现在已经有了它!

答案 2 :(得分:1)

您想要在某个时区查看日期的任何地方:

DateTime dtDateOfReading = TimeZoneInfo.ConvertTime(
    Convert.ToDateTime(myTables.Rows[i]["fldDateOfReading"]), 
    dtTimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")
    );

如果您想要查看多个时区,则需要将时区与日期或其所在的客户站点一起存储。

注意:请注意转换后的DateTime值,因为它们会有一种未指定的类型,在某些情况下可能会被假定(错误地)为本地。

编辑:将SQL连接的时区设置为与SQL Server的时区匹配可能更容易,但是本文:http://support.microsoft.com/kb/842545似乎表明SqlDataAdapter可能不支持时区配置。