I have the following code:
DataTable t = new DataTable();
t.Locale = CultureInfo.InvariantCulture;
t.Columns.Add("Date", typeof(DateTime));
DateTime today = DateTime.Now;
DateTime yesterday = today.AddDays(-1);
DateTime tomorow = today.AddDays(1);
t.Rows.Add(yesterday);
t.Rows.Add(today);
t.Rows.Add(tomorow);
string filter = string.Format(CultureInfo.InvariantCulture,
"Date >= #{0}# AND Date <= #{1}#", yesterday, tomorow);
t.DefaultView.RowFilter = filter;
foreach (DataRowView v in t.DefaultView)
Console.WriteLine(v["date"]);
I'm expecting that the filtered t.DefaultView
now contains all three "days". But for some reason the last date from the range isn't included. It seems <=
operator for DateTime
type works like a <
.
Where is the problem? Is that a bug? Any suggestions how to overcome that?
Update.
Got some responses about DateTime
type and comparison operators. Thanks.
But now I want to direct attention to filter expression.
Ok, say I have the folloving loop:
foreach (DataRow r in t.Rows)
{
DateTime date = (DateTime)r["Date"];
if (yesterday <= date && date <= tomorow)
Console.WriteLine(date);
}
This loop should show the same result like
foreach (DataRowView v in t.DefaultView)
Console.WriteLine(v["date"]);
from the previous example, yes? No! Here <=
works as I'm expecting and the result is all three days. Why?
Update #2: solution. As Joe has noted - the problem is about fractions of a second. If I format upper and lower bounds with Round-trip date/time pattern (to preserve fractions of a second) - everything works just fine:
string filter = string.Format(CultureInfo.InvariantCulture,
"Date >= '{0}' AND Date <= '{1}'",
yesterday.ToString("o", CultureInfo.InvariantCulture),
tomorow.ToString("o", CultureInfo.Inva开发者_运维知识库riantCulture));
The date comparison takes the time into account. So, for instance, "today at midday" is greater than just "today". If you use DateTime.Now
, the time is included. So, if DateTime.Now
is "today at midday", then tomorrow = today.AddDays(1)
is less than "tomorrow at 3PM"... So you need to ignore the time part of the date. You can do that by formatting the date without the time. Also, if you want to check that a date is "less or equal than tomorrow" (regardless of the time), check that it is "strictly less than the day after tomorrow" :
string filter = string.Format(CultureInfo.InvariantCulture,
"Date >= #{0:MM/dd/yyyy}# AND Date < #{1:MM/dd/yyyy}#",
yesterday,
tomorrow.AddDays(1));
The code you posted in your update is not equivalent to the row filter.
Your row filter formats the date using the general format for the current culture. This probably does not include fractions of a second - therefore unless you happen to call DateTime.Now on a second boundary, your tomorrow
value will be some fractions of a second beyond the range specified by the filter.
I.e. if your tomorrow
value is '2009-12-23 01:02:03.456', your row filter is only taking values up to and including '2009-12-23 01:02:03', a few fractions of a second before the value specified by tomorrow.
If you only want to compare dates, you should use DateTime.Date to truncate the time component from your dates (and use DateTime.Today rather than DateTime.Now for the current date).
Try with
DateTime today = DateTime.Today;
if does not solve, check whether your date field contains time also. there lies your problem.
Update: your second comment.
when you compare with DateTime.Now e.g. Date <= 21.12.2009 14:35:35, it will take all before 14:35 hours and will ignore later rows. Hope this helps you.
See following article to get more idea
http://dotnetguts.blogspot.com/2007/06/understanding-datetime-and-timespan-in.html
精彩评论