I was playing with dates using a C# program.
I want to filter on any table that has a DateTime, DateTime2, DateTimeOffset columns.
I store the LastRefreshDate
as DateTimeOffSet
in UTC and I use it to filter data on those tables. I adjust the offset (using NodaTime) of the LastRefreshDate
based on the timezone used to store the dates in those tables. Usually, it is given by the user.
So I created a test sample to explain the problem. Usually, the SQL queries are dynamic and the parameters as well. Here is the sample code:
[TestMethod]
public void Test()
{
using (SqlConnection connection = new SqlConnection("Server=myserver;Database=mydb;User ID=admin;Password=admin"))
{
connection.Open();
using (SqlCommand command = new SqlCommand("SELECT [TimeStamp] FROM [dbo].[DATA] WHERE [TimeStamp] >= @p0", connection))
{
string datestring = "2019-06-18 13:35:20.1133868 -04:00";
// Does not work
// DateTimeOffset p0 = DateTimeOffset.Parse(datestring, CultureInfo.InvariantCulture);
// Does work
DateTime p0 = DateTime.Parse(datestring, CultureInfo.InvariantCulture);
command.Parameters.AddWithValue("@p0", p0);
using (SqlDataReader reader = command.ExecuteReader())
{
var dataTable = new DataTable();
dataTable.Load(reader);
var result = dataTable.Rows.Count == 0;
}
}
}
}
I created 2 SQL fiddles that demonstrate the issue. By the way, I ran the SQL Server Profiler and the generated queries are similar to the queries in the fiddles.
DateTime fiddle: http://sqlfiddle.com/#!18/a06be/1
declare @p0 datetime = '2019-06-18 13:35:20'
SELECT
[TimeStamp]
FROM
[dbo].[DATA]
WHERE
([TimeStamp] >= @p0)
DateTimeOffSet fiddle: http://sqlfiddle.com/#!18/a06be/2
declare @p0 datetimeoffset(7) ='2019-06-18 13:35:20.1133868 -04:00'
SELECT [TimeStamp]
FROM
[dbo].[DATA]
WHERE
([TimeStamp] >= @p0 )
I did even more tests. By applying the cast directly, the SQL query works. It seems that SQL Server implicit conversion is not behaving in the same manner as an explicit cast. Here is the test case:
declare @p0 datetime
set @p0 = '2019-06-18 17:48:00.00'
declare @p1 datetimeoffset(7)
set @p1 = '2019-06-18 17:47:00.5385563 -04:00'
select 1
where @p0 > cast(@p1 as datetime) -- working
--where @p0 > @p1 -- not working