DateTimeOffset date не включает записи с конечной датой - PullRequest
0 голосов
/ 13 апреля 2020

Я хотел бы получить записи базы данных по диапазону дат, включая данные с включенным диапазоном дат окончания. Столбец TimeStamp в базе данных имеет тип dateTime2(7). Дата и время хранятся в UTC. Но я отображаю данные, основанные на часовом поясе пользователей. Чтобы добиться этого, я ищу часовой пояс и затем конвертирую его в BaseUtfOffset в C#. Ex. 3/18/2020 и 3/29/2020

 var newOffSetDate = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);

 DateTimeOffset d1 = new DateTimeOffset(Convert.ToDateTime(date1), newOffSetDate.BaseUtcOffset);
 DateTimeOffset d2 = new DateTimeOffset(Convert.ToDateTime(date2), newOffSetDate.BaseUtcOffset);

Затем я передаю начальную и конечную даты в процедуре (тип параметра DateTimeOffset), созданной здесь, чтобы сделать простой оператор выбора в SQL. Возвращенные данные включают только записи с датой начала.

create table MyTable
(
  Id int Primary Key Identity(1,1),
  [TimeStamp] datetime2(7) not null
)

insert into MyTable(TimeStamp) values('2020-03-29 19:40:46.8500000')
insert into MyTable(TimeStamp) values('2020-03-29 19:40:53.1000000')
insert into MyTable(TimeStamp) values('2020-03-18 17:15:48.2600000')

select * from MyTable
where
convert(datetimeoffset, convert(datetime2(7), timestamp, 1)) >= '3/18/2020 12:00:00 AM -04:00' and 
convert(datetimeoffset, convert(datetime2(7), timestamp, 1)) <= '3/29/2020 12:00:00 AM -04:00'

Например, в приведенном выше сценарии я должен получить ВСЕ записи, но я получаю только одну запись.

2020-03-18 17: 15: 48.2600000

Влияет ли формат DateTimeOffset, полученный в C#, на результаты или я что-то упустил?

SQLFIDDLE

ОБНОВЛЕНИЕ:

Параметры хранимой процедуры:

,@StartDate     DateTimeOffset  = NULL
,@EndDate       DateTimeOffset  = NULL

В примере используется: дата начала 3/18/2019 и дата окончания 3/29/2020 , Метод C#, который преобразует даты в DateTimeOffset, выдает следующий вывод:

d1 = 3/18/2020 12:00:00 AM -04:00
d2 = 3/29/2020 12:00:00 AM -04:00

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Я полагаю, что вы делаете это сложнее, чем нужно.

В вашем коде : примените TimeZoneInfo к DateTime аргументам, предоставленным пользователем. Поскольку данные сохраняются как DateTime2, используйте типы параметров, которые соответствуют в этом случае System.DateTime. Исходя из вашего вопроса, вы хотите, чтобы верхнее значение было инклюзивным, а с датами проще всего добавить 1 к значению даты (или 24 часа также допустимо) и изменить запрос на меньше , чем .

См. Код ниже, вы можете изменить его, чтобы он был сохраненным профессионалом c. вместо.

public void Test(DateTime argStartDate, DateTime argEndDate)
{
    var newOffSetDate = System.TimeZoneInfo.FindSystemTimeZoneById("");

    DateTime startParam = new DateTimeOffset(argStartDate, newOffSetDate.GetUtcOffset(argStartDate)).UtcDateTime;
    DateTime endParam = new DateTimeOffset(argEndDate, newOffSetDate.GetUtcOffset(argEndDate)).UtcDateTime;

    endParam = endParam.AddDays(1);

    const string query = "SELECT [column1], [column2], ... FROM [YourTable] WHERE [TimeStamp] >= @start AND [TimeStamp] < @end";
    using (var con = new System.Data.SqlClient.SqlConnection(""))
    using (var com = new System.Data.SqlClient.SqlCommand(query, con))
    {
        com.Parameters.Add("@start", SqlDbType.DateTime2).Value = startParam;
        com.Parameters.Add("@end", SqlDbType.DateTime2).Value = endParam;
        con.Open();
        using (var reader = com.ExecuteReader())
        {
            while (reader.Read())
            {
                // do stuff
            }
        }
    }
}
0 голосов
/ 13 апреля 2020

Причина, по которой ваш запрос возвращает строку, в том, что это правильно. У вас есть 3 раза, которые вы называете UT C:

2020-03-29 19:40:46.8500000+00:00
2020-03-29 19:40:53.1000000+00:00
2020-03-18 17:15:48.2600000+00:00

Давайте поэтому преобразовать их в -04:00 (что EDT):

2020-03-29 15:40:46.8500000-04:00
2020-03-29 15:40:53.1000000-04:00
2020-03-18 13:15:48.2600000-04:00

Затем вы должны проверьте, включены ли времена или после 2020-03-18T00:00:00-04:00 и затем или до 2020-03-29T00:00:00-04:00.

2020-03-18 13:15:48.2600000-04:00 и после 2020-03-18T00:00:00-04:00, и до 2020-03-29T00:00:00-04:00, так что это дисплей. С другой стороны, оба 2020-03-29 15:40:53.1000000-04:00 и 2020-03-29 15:40:46.8500000-04:00 равны после 2020-03-29T00:00:00-04:00 и поэтому не отображаются.

Вы получаете 1 строку, потому что только 1 из этих строк выполняет там WHERE.

...