DateTimeOffset 日期不包括结束日期的记录
DateTimeOffset date doesn't include records with end date
我想按日期范围获取数据库记录,包括包含结束日期范围的数据。数据库中的 TimeStamp
列是 dateTime2(7)
的类型。日期和时间存储在 UTC
中。但是,我根据用户时区显示数据。为此,我正在查找时区,然后将其转换为 C#
中的 BaseUtfOffset
。前任。 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 中执行一个简单的 select 语句。返回的数据只包括开始日期的记录。
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
在 C#
中生成的 DateTimeOffset
的格式是否会影响结果,还是我遗漏了什么?
更新:
存储过程参数:
,@StartDate DateTimeOffset = NULL
,@EndDate DateTimeOffset = NULL
示例中使用了:开始日期 3/18/2019
和结束日期 3/29/2020
。将日期转换为 DateTimeOffset 的 C# 方法产生了以下输出:
d1 = 3/18/2020 12:00:00 AM -04:00
d2 = 3/29/2020 12:00:00 AM -04:00
您的查询返回行的原因是正确的。你有 3 次,你说的是 UTC:
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
。
我相信你让它变得比需要的更难。
在您的代码中:将 TimeZoneInfo
应用于用户提供的 DateTime
参数。由于数据持久化为 DateTime2
,因此使用在本例中匹配的参数类型 System.DateTime
。根据您的问题,您希望上限值包含在内,使用日期最简单的方法是将日期值加 1(或者 24 小时也是可以接受的)并将查询更改为 less比.
看下面的代码,可以修改为存储过程。相反。
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
}
}
}
}
我想按日期范围获取数据库记录,包括包含结束日期范围的数据。数据库中的 TimeStamp
列是 dateTime2(7)
的类型。日期和时间存储在 UTC
中。但是,我根据用户时区显示数据。为此,我正在查找时区,然后将其转换为 C#
中的 BaseUtfOffset
。前任。 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 中执行一个简单的 select 语句。返回的数据只包括开始日期的记录。
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
在 C#
中生成的 DateTimeOffset
的格式是否会影响结果,还是我遗漏了什么?
更新:
存储过程参数:
,@StartDate DateTimeOffset = NULL
,@EndDate DateTimeOffset = NULL
示例中使用了:开始日期 3/18/2019
和结束日期 3/29/2020
。将日期转换为 DateTimeOffset 的 C# 方法产生了以下输出:
d1 = 3/18/2020 12:00:00 AM -04:00
d2 = 3/29/2020 12:00:00 AM -04:00
您的查询返回行的原因是正确的。你有 3 次,你说的是 UTC:
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
。
我相信你让它变得比需要的更难。
在您的代码中:将 TimeZoneInfo
应用于用户提供的 DateTime
参数。由于数据持久化为 DateTime2
,因此使用在本例中匹配的参数类型 System.DateTime
。根据您的问题,您希望上限值包含在内,使用日期最简单的方法是将日期值加 1(或者 24 小时也是可以接受的)并将查询更改为 less比.
看下面的代码,可以修改为存储过程。相反。
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
}
}
}
}