web-dev-qa-db-fra.com

Comment comparer DateTime sans heure via LINQ?

J'ai

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

Mais il compare en incluant la partie temps de DateTime. Je n'en ai vraiment pas besoin.

Comment le faire sans temps?

Merci!

54
Developer

Utilisez simplement la propriété Date:

var today = DateTime.Today;

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

Notez que j'ai explicitement évalué DateTime.Today une fois pour que la requête soit cohérente - sinon à chaque fois que la requête est exécutée, et même dans l'exécution, Today peut changer, vous obtiendrez des résultats incohérents. Par exemple, supposons que vous disposiez des données de:

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

Certes, soit les deux entrées 1 et 3 devraient figurer dans les résultats, soit ni l’un des deux d'entre eux devraient ... mais si vous évaluez DateTime.Today et il change le 9 mars après avoir effectué les deux premières vérifications, vous pouvez vous retrouver avec les entrées 1, 2, 4.

Bien sûr, en utilisant DateTime.Today suppose que vous êtes intéressé par la date dans le fuseau horaire local . Cela peut ne pas être approprié, et vous devriez vous assurer absolument que vous savez ce que vous voulez dire. Vous pouvez utiliser DateTime.UtcNow.Date à la place, par exemple. Malheureusement, DateTime est une bête glissante ...

EDIT: Vous pouvez également vous débarrasser des appels à DateTime propriétés statiques - ils rendent le code difficile à tester. Dans Noda Time , nous avons une interface spécialement conçue à cet effet ( IClock ) que nous nous attendons à recevoir de manière appropriée. Il existe une implémentation "heure système" pour la production et une implémentation "stub" pour les tests, ou vous pouvez l'implémenter vous-même.

Vous pouvez utiliser la même idée sans utiliser Noda Time, bien sûr. Pour tester à l'unité ce code particulier, vous voudrez peut-être indiquer la date, mais vous l'obtiendrez de quelque part - et l'injection d'une horloge signifie vous pouvez tester tout le code.

68
Jon Skeet

LINQ to Entities ne prend pas en charge la propriété Date. Si vous essayez de l'utiliser sur un champ DateTime dans une requête LINQ to Entities, vous obtiendrez une erreur. Vous pouvez cependant supprimer les dates à l’aide de la méthode DbFunctions.TruncateTime.

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

Essayez ce code

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

Il arrive que LINQ n'aime pas les propriétés telles que DateTime.Date. Il ne peut tout simplement pas convertir en requêtes SQL. J'ai donc trouvé un moyen de comparer les dates en utilisant la réponse de Jon, mais sans ce vilain DateTime.Date. Quelque chose comme ça:

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

De cette façon, nous comparons une base de données complète DateTime, avec tous ces éléments de date et d'heure, comme 2015-03-04 11: 49: 45.000 ou quelque chose du genre, avec un DateTime qui représente la première milliseconde de la journée, comme 2015-03-04 00: 00: 00.0000.

Toute date/heure comparée à DateTime.Today Nous renverra en toute sécurité si cette date est postérieure ou identique. Sauf si vous voulez comparer littéralement le même jour, auquel cas je pense que vous devriez chercher la réponse de César.

La méthode DateTime.CompareTo() est juste un truc fantaisiste orienté objet. Il renvoie -1 si le paramètre est antérieur à la date et l'heure que vous avez référencées, 0 s'il est littéralement égal (avec tout ce que vous avez écrit) et 1 s'il est ultérieur.

9
Joao Arruda

J'ai trouvé que dans mon cas, c'est la seule façon de fonctionner: (dans mon application, je veux supprimer les anciennes entrées du journal)

 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));

Je ne comprends pas pourquoi la solution de Jon ne fonctionne pas ...

9
Caesar

Le .Date _ La réponse est trompeuse, car vous obtenez l'erreur mentionnée précédemment. Une autre façon de comparer, autre que celle mentionnée DbFunctions.TruncateTime, peut aussi être:

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)

Cela a l'air mieux (plus lisible) dans la requête SQL générée. Mais j'avoue que cela semble pire dans le code XD en C #. J'étais en train de tester quelque chose et il semblait que TruncateTime ne fonctionnait pas pour moi, malheureusement, la faute était entre le clavier et le fauteuil, mais dans l'intervalle, j'ai trouvé cette alternative.

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

J'ai trouvé cette question alors que j'étais coincé avec la même requête. Je l'ai finalement trouvé sans utiliser DbFunctions. Essaye ça:

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);

De cette façon, en bifurquant les parties de date, nous comparons effectivement uniquement les dates, laissant ainsi de côté l'heure.

J'espère que ça t'as aidé. Pardonnez-moi pour le formatage dans la réponse, ceci est ma première réponse.

1
Sushmit Saxena

Essayer

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