在某一天结束时获取DateTime

时间:2014-01-31 22:52:42

标签: c# datetime

我有以下

 DateTime today = DateTime.Today; // or DateTime.UtcNow.Date;

现在,我无法在Linq-EF中执行此类操作,因为Date无法转换为SQL:

 context.Records.Where(r => r.CreationDate.Date == today);

所以,我总是做这样的事情:

 DateTime dayEnd = today.AddDays(1).AddMilliseconds(-1);
 context.Records.Where(r => r.CreationDate >= today && r.CreationDate <= dayEnd);

现在,有没有更好的方法来结束时间DateTime而不是增加一天然后花费一毫秒?

4 个答案:

答案 0 :(得分:5)

改为使用EntityFunctions.TruncateTime

context.Records.Where(r => EntityFunctions.TruncateTime(r.CreationDate) == today);

您还可以通过将条件更改为AddSeconds(-1)来跳过<

DateTime tomorrow = today.AddDays(1);
context.Records.Where(r => r.CreationDate >= today && r.CreationDate < tomorrow);

答案 1 :(得分:1)

您可以使用EntityFunctions.TruncateTime

context.Records.Where(r => EntityFunctions.TruncateTime(r.CreationDate) == today);

答案 2 :(得分:1)

将SqlFunction用于“dayofyear”和“year”:

context.Records.Where(r => 
SqlFunctions.DatePart("dayofyear", r.CreationDate) == DateTime.Now.DayOfYear 
&& SqlFunctions.DatePart("year", r.CreationDate) == DateTime.Now.Year);

答案 3 :(得分:1)

这样的问题
DateTime today = DateTime.Today ;
Context.Records.Where(r => EntityFunctions.TruncateTime(r.CreationDate) == today) ;

底层SQL可能看起来像这样:

select *
from some_table r
where convert(date,r.CreationDate) == @today

由于该列现在是表达式的一部分,因此SQL引擎无法使用它可用的任何覆盖索引。除非你有其他标准可以使用索引,否则你将进行表扫描。对于大表,这将导致性能问题。

你应该避免明显的

DateTime today  = DateTime.Today ;
DateTime dayEnd = today.AddDays(1).AddMilliseconds(-1);
context.Records.Where(r => r.CreationDate >= today && r.CreationDate <= dayEnd) ;

由于SQL Server datetime值的工作方式:当它们以毫秒计数时,SQL Server的“滴答”以3毫秒和4毫秒的增量发生。有关详细信息,请参阅问题my answerHow does SqlDateTime do its precision reduction。但简而言之:

  

要以SQL Server的方式进行转换,请执行以下操作:   取考虑的实际时间的毫秒部分,值为0-999,   模数100.它为您提供低位数字,从0到9的值。所以如果是当前时间   是23:57:23.559,毫秒组件是559.模数100你得到9。

     
      
  1. 值0和1“向下舍入”为0.
  2.   
  3. 值2,3和4是“向下舍入”至“3”。
  4.   
  5. 值5,6,7和8“向下舍入”为7。
  6.   
  7. 值为9将 UP 舍入为0.这有一个相当不愉快和讨厌的一面   效果:如果时间的毫秒部分是999,则它会上升1毫秒。这个   表示时间23:59:59.999向上舍入为下一天。所以'31的转换   2010年12月23日:59:59.999'的日期时间值为... 2011年1月1日00:00:00.000。
  8.   

请注意,smalldatetime也表现出这种行为。只有datetime2可以免除。

<强>因此...

除非你小心谨慎,否则很容易将掉落在地板上的东西放在正确的时间戳上(不要问我怎么知道)。

你最好做一些像

这样的事情
DateTime today    = DateTime.Today ;
DateTime tomorrow = today.AddDays(1);
context.Records.Where(r => r.CreationDate >= today && r.CreationDate < tomorrow) ;

应该转换为类似

的SQL
select *
from some_table r
where r.CreationDate >= @today
  and r.CreationDate <  @tomorrow

并允许优化器使用日期/时间列上的索引。