Я играл с датами, используя программу на C #.
Я хочу выполнить фильтрацию для любой таблицы, в которой есть столбцы DateTime, DateTime2, DateTimeOffset.
Я храню LastRefreshDate
как DateTimeOffSet
в UTC и использую его для фильтрации данных в этих таблицах. Я корректирую смещение (используя NodaTime) LastRefreshDate
на основе часового пояса, используемого для хранения дат в этих таблицах. Обычно это дается пользователем.
Итак, я создал тестовый образец, чтобы объяснить проблему. Как правило, запросы SQL являются динамическими, а также параметры. Вот пример кода:
[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;
}
}
}
}
Я создал 2 скрипты SQL, которые демонстрируют проблему. Кстати, я запустил SQL Server Profiler, и сгенерированные запросы аналогичны запросам в скриптах.
Скрипка DateTime: 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 )
Я сделал еще больше тестов. Применяя приведение напрямую, SQL-запрос работает. Кажется, что SQL Server неявное преобразование не ведет себя так же, как явное приведение. Вот тестовый пример:
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