C# DateTimeOffset日期不包括具有结束日期的记录
我想按日期范围获取数据库记录,包括包含结束日期范围的数据。数据库中的时间戳列是dateTime27的一种类型。日期和时间存储在UTC中。但是,我根据用户时区显示数据。为了实现这一点,我正在查找时区,然后将其转换为C.Ex.3/18/2020和3/29/2020中的BaseUtfOffset 然后,我在这里创建的DateTimeOffset参数的过程类型中传递开始日期和结束日期,以便在SQL中执行简单的select语句。返回的数据仅包括具有开始日期的记录C# DateTimeOffset日期不包括具有结束日期的记录,c#,sql-server-2016,datetimeoffset,C#,Sql Server 2016,Datetimeoffset,我想按日期范围获取数据库记录,包括包含结束日期范围的数据。数据库中的时间戳列是dateTime27的一种类型。日期和时间存储在UTC中。但是,我根据用户时区显示数据。为了实现这一点,我正在查找时区,然后将其转换为C.Ex.3/18/2020和3/29/2020中的BaseUtfOffset 然后,我在这里创建的DateTimeOffset参数的过程类型中传递开始日期和结束日期,以便在SQL中执行简单的select语句。返回的数据仅包括具有开始日期的记录 create table MyTable
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'
在本例中使用:开始日期为2019年3月18日,结束日期为2020年3月29日。将日期转换为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行满足了那里的要求。我相信你让它变得比需要的更困难了 在代码中:将TimeZoneInfo应用于用户提供的DateTime参数。由于数据被持久化为DateTime2,因此请使用在本例中匹配的参数类型System.DateTime。根据您的问题,您希望上限值包含日期,最简单的方法是在日期值中添加1,或者也可以接受24小时,并将查询更改为小于 请参阅下面的代码,您可以将其修改为存储过程。相反
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
}
}
}
}
convertdatetime27,timestamp,1试图在这里实现什么?timestames已经是一个datetime2 s将其转换为一只会减慢查询速度。@Larnu,我不需要进行任何转换就得到了相同的结果。这是我最近一次尝试将日期时间转换为2020-03-29 19:40:46.8500000+00:00,这可能会奏效,但不可否认,不会。如果你想过滤一个包含日期的范围,那么你需要将时间也包括在你的上限范围内。最简单的方法是将1添加到日期,并将过滤器更改为刚好小于。示例:用户希望在日期3/18和3/29之间进行筛选。使where子句大于或等于2020-3-18,小于2020-3-30。此评论没有考虑时区,只是为了说明时间在where子句中很重要,而您目前没有对其进行说明。关于时区。如果将日期持久化为datetime2,并且日期信息为UTC,则需要将输入参数转换为UTC,然后根据这些参数进行过滤。2020-03-29 19:40:53.1000000+00:00在2020-03-29T00:00:00-04:00之后,因此convertdatetimeoffset,convertdatetime27,timestamp,1 ooo。我现在明白你刚才在评论中所指的了。所以我想我要找的是截止日期应该是2020年3月29日23:59:00 PM-04:00?我想,也许我没有解释清楚我的要求。我也会更新这个问题。我需要的是,如果用户的本地日期在日期范围内,我希望在不考虑时间的情况下包括该日期。因此,对于2020年3月18日和2020年3月29日,我希望所有记录都在该日期下,而不必担心时间。在这种情况下,我发现是我的转换导致了问题。如果您想要3月29日的所有日期,而不考虑时间,那么使用<2020-03-30T00:00:00-04:00,@smr5.Igor,您是对的。我把事情复杂化了。谢谢
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
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
}
}
}
}