Using SQL Server 2008. This is a really junior question and I could really use some elaborate information, but the information on Google seems to dance around the topic quite a bit and it would be nice if there was some detailed elaboration on how this works…
Let’s say I have a datetime column and in ADO.NET I set it to DateTime.UtcNow.
1) Does SQL Server store DateTime.UtcNow accordingly, or does it offset it again based on the timezone of where the server is installed, and then return it offset-reversed when queried? I think I know that the answer is “of course it stores it without offsetting it again” but want to be certain.
So then I query for it and cast it from object to a DateTime after getting it from, say, an IDataReader column. As far as I know, System.DateTime has metadata that internally tracks whether it is a UTC DateTime or it is an offsetted DateTime, which may or may not cause .ToLocalTime() and .ToUniversalTime() to have different behavior depending on this state. So,
2) Does this casted System.DateTime object already know that it is a UTC DateTime instance, or does it assume that it has been offset?
Now let’s say I don’t use UtcNow, I use DateTime.Now, when performing an ADO.NET INSERT or UPDATE.
3) Does ADO.NET pass the offset to SQL Server and does SQL Server store DateTime.Now with the offset metadata?
So then I query for it and cast it from, say, an IDataReader column to a DateTime.
4) Does this casted System.DateTime object already know that it is an offset time, or does it assume that it is UTC?
Performed some unit tests to answer my own question in all four parts.
###1: Does SQL Server store DateTime.UtcNow accordingly, or does it offset it again based on the timezone of where the server is installed, and then return it offset-reversed when queried?
Executed this):
The result of this at 1:30 PM local time (-7h, or 8:30 PM UTC) was:
Then I tried this:
Executed at 9:25 PM UTC, it returned
Compare this to DateTime.Now:
Executed at 3:55 PM (local; -7h), returned:
###2: So then I query for it and cast it from object to a DateTime after getting it from, say, an IDataReader column. Does this casted System.DateTime object already know that it is a UTC DateTime instance, or does it assume that it has been offset?
Neither.
The result of this (executed at 1:58 PM local time) was:
That is,
.ToUniversalTime()ended up offsetting from local time to UTC time not once but twice (??), and.ToLocalTime()ended up not offsetting at all.###3: Does ADO.NET pass the offset to SQL Server and does SQL Server store DateTime.Now with the offset metadata?
Without performing any unit tests, the answer is already known to be "only with DateTimeOffset" SQL type. SQL’s
datetimedoes not do offsets.###4: Does this casted System.DateTime object already know that it is an offset time, or does it assume that it is UTC?
Neither. SQL’s DateTimeOffset type is returned as a .NET DateTimeOffset struct.
The following executed at 3:31 PM local time where column
offvalis a datetimeoffset SQL type,This resulted in:
A surprising disparity.
Going back and executing the test for question #1 above using DateTime.Now instead of DateTime.UtcNow, I validated that ADO.NET does NOT convert to universal time before storing to the database.
That is, this executed at 3:27 PM local time (-7h):
.. returned ..
Executing this at 3:17 PM local time:
Resulted in:
Compare this to DateTime.Now:
Executed at 3:58 PM (local, -7h):