web-dev-qa-db-ja.com

LINQを介して時間なしでDateTimeを比較する方法は?

私は持っています

var q = db.Games.Where(t => t.StartDate >= DateTime.Now).OrderBy(d => d.StartDate);

ただし、DateTimeの時間部分を含めて比較します。本当に必要ありません。

時間なしでそれを行う方法?

ありがとうございました!

54
Developer

Dateプロパティを使用するだけです:

var today = DateTime.Today;

var q = db.Games.Where(t => t.StartDate.Date >= today)
                .OrderBy(t => t.StartDate);

DateTime.Todayonceを明示的に評価したため、クエリが一貫していることに注意してください。そうでない場合は、クエリが実行されるたびに、within実行中、Todayは変更される可能性があるため、一貫性のない結果が得られます。たとえば、次のデータがあるとします。

Entry 1: March 8th, 8am
Entry 2: March 10th, 10pm
Entry 3: March 8th, 5am
Entry 4: March 9th, 8pm

確かにbothエントリ1と3が結果に含まれるか、neitherのうち、...が評価される必要がありますが、DateTime.Todayを評価し、最初の2つのチェックを実行した後、3月9日にchangesを変更すると、エントリ1、2、4になります。

もちろん、DateTime.Todayを使用すると、localタイムゾーンの日付に関心があると想定されます。それは適切ではないかもしれないので、絶対に確認してください。たとえば、may代わりにDateTime.UtcNow.Dateを使用したい場合があります。残念ながら、 DateTimeは滑りやすい獣です ...

編集:DateTime静的プロパティへの呼び出しを完全に削除することもできます。これにより、コードの単体テストが難しくなります。 Noda Time には、この目的専用のインターフェイス( IClock )があり、適切にインジェクトされることが期待されます。実稼働用の「システム時間」実装とテスト用の「スタブ」実装がありますが、自分で実装することもできます。

もちろん、野田タイムを使用せずに同じアイデアを使用できます。この特定のコードを単体テストするには、日付を渡す必要がありますが、somewhereから取得し、クロックを挿入することを意味しますコードをテストallできます。

68
Jon Skeet

DateプロパティはLINQ to Entitiesではサポートされていません。LINQto EntitiesクエリのDateTimeフィールドで使用しようとするとエラーが発生します。ただし、DbFunctions.TruncateTimeメソッドを使用して日付をトリムできます。

var today = DateTime.Today;
var q = db.Games.Where(t => DbFunctions.TruncateTime(t.StartDate) >= today);
94
Duane Theriot

このコードを試してください

var today = DateTime.Today;
var q = db.Games.Where(t => DbFunctions.TruncateTime(t.StartDate) <= today);
20
Cagdas

LINQは_DateTime.Date_などのプロパティを好まないことがあります。 SQLクエリに変換できません。そこで、Jonの答えを使用して日付を比較する方法を見つけましたが、そのわんぱくな_DateTime.Date_はありませんでした。このようなもの:

var q = db.Games.Where(t => t.StartDate.CompareTo(DateTime.Today) >= 0).OrderBy(d => d.StartDate);

このように、完全なデータベースDateTimeを、2015-03-04 11:49:45.000などのすべての日時と、その日の実際の最初のミリ秒を表すDateTimeと比較しています。 2015-03-04 00:00:00.0000。

その_DateTime.Today_と比較するDateTimeは、その日付がより遅いか同じ場合に安全に返されます。文字通り同じ日に比較したい場合を除き、その場合は、Caesarの答えに行くべきだと思います。

メソッドDateTime.CompareTo()は、単なるオブジェクト指向のものです。パラメーターが参照したDateTimeよりも前の場合は-1を返し、LITERALLY EQUAL(すべてのタイムリーなものを含む)の場合は0を返し、それ以降の場合は1を返します。

9
Joao Arruda

私の場合、これが唯一の動作方法であることがわかりました:(私のアプリケーションでは、古いログエントリを削除したいです)

 var filterDate = dtRemoveLogs.SelectedDate.Value.Date;
 var loadOp = context.Load<ApplicationLog>(context.GetApplicationLogsQuery()
              .Where(l => l.DateTime.Year <= filterDate.Year
                       && l.DateTime.Month <= filterDate.Month
                       && l.DateTime.Day <= filterDate.Day));

ジョンのソリューションが機能しない理由がわかりません。

9
Caesar

.Dateの回答は、前述のエラーが発生するため誤解を招きます。前述のDbFunctions.TruncateTime以外の比較する別の方法は、

DateTime today = DateTime.Now.date;
var q = db.Games.Where(t => SqlFunctions.DateDiff("dayofyear", today, t.StartDate) <= 0
      && SqlFunctions.DateDiff("year", today, t.StartDate) <= 0)

生成されたSQLクエリの方が見やすく(読みやすく)なります。しかし、C#コードXDの方が悪いように見えます。私は何かをテストしていましたが、残念ながらTruncateTimeは機能していなかったようです。残念ながらキーボードと椅子の間に障害がありましたが、その間にこの代替手段を見つけました。

2
Tomáš Florek
DateTime dt=DateTime.Now.date;

var q = db.Games.Where(
    t =>EntityFunction.TruncateTime(t.StartDate.Date >=EntityFunction.TruncateTime(dt)).OrderBy(d => d.StartDate
);
1
Ramanand Potdar

私は同じ質問にこだわっている間にこの質問を見つけました。 DbFunctionsを使用せずに最終的に見つけました。これを試して:

var q = db.Games.Where(t => t.StartDate.Day == DateTime.Now.Day && t.StartDate.Month == DateTime.Now.Month && t.StartDate.Year == DateTime.Now.Year ).OrderBy(d => d.StartDate);

このように、日付部分を分岐することにより、日付のみを効果的に比較し、時間を省略します。

お役に立てば幸いです。回答の書式設定をご容赦ください。これが私の最初の回答です。

1
Sushmit Saxena

試して

var q = db.Games.Where(t => t.StartDate.Date >= DateTime.Now.Date).OrderBy(d => d.StartDate);
1
Matt Burland