I have a list of DateTime objects.
I need to take from this list only those objects that have time part of the date between '00:00:01' and '12:00:00'.
How can I query this list?
If I would make a SQL Query I would do something this way
SELECT TspCreated,
CASE
WHEN cast(TspCreated as time) > '00:00:00' AND
cast(TspCreated as time) <= '12:00:00'
THEN '00 - 12'
WHEN cast(TspCreated as time) > '12:00:00' AND
cast(TspCreated as time) <= '18:00:00'
THEN '12 - 18'
WHEN cast(TspCreated as time) > '18:00:00' AND
cast(TspCreated as time) <= '23:59:59'
THEN '18 - 24'
END AS TimeFrame
FROM MyTable
EDIT:
Thanks to Jon Skeet answer I had the way to use Timespan objects as the boundaries for my query. Unfortunately, in my case that answer is not applicable because Linq-to-Entities does not support usage of TimeOfDay
property. I have ended up with usage of Entity Framework Canonical Functions:
TimeSpan ts_0 = new TimeSpan( 0, 0, 0 );
TimeSpan ts_12 = new TimeSpan( 12, 0, 0 );
int NumOfIssues = ctx.MyEntitySet.Where( x =>
DbFunctions.CreateTime( x.TspUsed.Hour, x.TspUsed.Minute, x.TspUsed.Second ) >= ts_0 &&
DbFunctions.CreateTime( x.TspUsed.Hour, x.TspUsed.Minute, x.TspUsed.Second ) < ts_12).Count();
It seems to me that all you need is the DateTime.TimeOfDay
property. I would then recommend changing your conditions slightly if you're able to, so that the lower bound is inclusive and the upper bound is exclusive, e.g.
var time = dateTime.TimeOfDay;
if (time.Hours < 12)
{
Console.WriteLine("Morning");
}
else if (time.Hours < 18)
{
Console.WriteLine("Afternoon");
}
else
{
Console.WriteLine("Evening");
}
As an example of why that's handy, your current classification excludes midnight entirely along with anything between 11:59:59pm and midnight, e.g. 11:59:59.999.
Or you could create appropriate TimeSpan
values for the boundaries and use the regular <
, <=
etc operators. For example:
TimeSpan noon = new TimeSpan(12, 0, 0);
TimeSpan sixPm = new TimeSpan(18, 0, 0);
TimeSpan time = dateTime.TimeOfDay;
if (time < noon)
{
...
}
else if (time < sixPm)
{
...
}
else
{
...
}
Note that with both approaches, I'm only checking one condition per if
statement, because I basically move through the day, from midnight onwards. If you just wanted to check one band in the middle, you could say:
if (noon <= time && time < sixPm)
As a slight aside, I've never liked that TimeOfDay
returns a TimeSpan
- an elapsed period of time isn't the same as a time of day. If you feel the same and you're doing any significant amount of date/time work, you might want to consider looking at my Noda Time project, which has a lot more types to represent various aspects of dates and times.
See more on this question at Stackoverflow