5

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

例如,当纽约的用户输入“2012-12-20 00:00”的 DateTime 值时,我希望加利福尼亚的用户看到相同的 DateTime 值。这些 DateTime 值不应该尊重时区的差异,但这就是我看到的情况。目前,SQL Server 会将 DateTime 作为“2012-12-19 21:00”交付给加利福尼亚用户。请注意由于从 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 值传递给我的方式有所不同。

我错过了什么?

4

3 回答 3

2

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

服务器端,使用getutcdate()而不是getdate().

于 2012-12-05T14:56:20.587 回答
2

感谢各位好心人的意见,以及根据您的建议进行的一些研究,我们已经解决了我们的问题。

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

该链接最终被证明是灵丹妙药。

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

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

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

再次感谢;我想我们现在明白了!

于 2012-12-05T19:21:36.407 回答
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 支持。

于 2012-12-05T15:43:58.890 回答