问题
My situation is that we store data in a SQL Server database, supporting 2005 on up. When a DateTime value is stored, it is in the local time of the client. I need to be able to get that date back on any other client, anywhere, without respect to whatever time zone that other client might be in.
So for instance, when a user in New York enters a DateTime value of "2012-12-20 00:00", I want the user in California to see that very same DateTime value. These DateTime values should not respect the difference in time zones, but that is what I see happening. Currently, SQL Server would deliver that DateTime to the California user as "2012-12-19 21:00". Notice how it's now the previous day because of the -3 hour rollback due to the change from EST to PST (forget about DST issues for the purposes of this conversation).
Getting that data back verbatim, and not translated by time zone, is what I need to accomplish. So what advice can you offer?
Some code to consider:
Here is the table:
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)),
We have a Sql class that does the work, and in the following example "sql" is an object of that class. The call is made using a parameterized query where @data0 is the DateTime object to store in a SQL DateTime field:
sql.Execute(@"INSERT INTO tblMeterReadings (fldMeterID, fldDateOfReading) VALUES (" + MeterID + ", @data0)", Date);
Ultimately, this sets up an SqlCommand, assigns parameters, and fires a command.ExecuteNonQuery() call.
Now, to retrieve the date, I simply select it into a DataTable (again, using our Sql class helper):
DataTable myTable = sql.readDataTable(@"SELECT fldMeterID, fldDateOfReading FROM tblMeterReadings");
So what I see is that in the database itself, the date is "2012-12-20 00:00" as I expect, but when I inspect the myTable contents in debug, I see that the date in that table is "2012-12-19 21:00".
The database was created on a SQL Server that runs on a machine in an EST state. My machine, however, is set to PST. Hence the difference in how the DateTime value is delivered to me in the SELECT.
What am I missing?
回答1:
Store the UTC date in the database. Only convert it to local time when displaying it in a client.
Server side, use getutcdate()
instead of getdate()
.
回答2:
Thanks to the input from you fine folks, and some research along the lines of your suggestions, we have resolved our issue.
A special thanks to ebyrob for the assistance and this link: http://support.microsoft.com/kb/842545
That link ultimately proved to be the silver bullet.
The fundamental issue is that when you construct a DataTable or DataSet, information about the time zone in which it is created is encoded with it. Then, if you pass that object across a connection to a machine that exists within a different time zone, any DateTime values in there will be adjusted based on the difference in time zones.
In light of that understanding, the fix is to set the DateTimeMode
property of all DateTime DataColumns to DataSetDateTime.Unspecified
. This prevents the post-serialization date adjustments, instead delivering the DateTime values verbatim.
I also want to point out that the article specifies DataSet, but we have proven DataTable is also vulnerable. In fact, I'm quite certain that it comes down to the DataColumn itself (those with a type of DateTime, anyway). I think the article states this as well.
So thanks again; I think we've got it now!
回答3:
Anywhere you want to view dates in a certain timezone you can do:
DateTime dtDateOfReading = TimeZoneInfo.ConvertTime(
Convert.ToDateTime(myTables.Rows[i]["fldDateOfReading"]),
dtTimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")
);
If you have more than one time-zone you want to view things in, you'll need to store the time-zone with either the date or which customer-site it goes with.
Note: Be careful with the converted DateTime values because they'll have a Kind of Unspecified which may be assumed (incorrectly) to be local in some cases.
EDIT: It might be easier to just set the Timezone for the SQL connection to match the timezone of the SQL Server, but this article: http://support.microsoft.com/kb/842545 seems to indicate that timezone configuration may not be supported by SqlDataAdapter at least.
来源:https://stackoverflow.com/questions/13725924/how-can-i-get-datetime-data-from-sql-server-ignoring-time-zone-issues