Getting today, past, and tomorrows list of appointments - c#

I have a problem when it comes to getting dates and times to be displayed as a list on the view page of my application.
Example:
public IList<Appointment> GetTodaysAppointments()
{
DateTime today = DateTime.Now.Date;
return db.Appointments
.Where(e => e.StartDateTimeBooking == today)
.Include(e => e.Patient)
.ThenInclude(p => p.User)
.Include(e => e.Doctor)
.ThenInclude(d => d.User)
.OrderBy(d => d.StartDateTimeBooking)
.ToList();
}
This is my code and to save repeating code to get tomorrow and past appointments this would be the same outlook for the code.
I have tried implementing the operator "<". This works great for past appointments and will only display past appointments and nothing else.
The Issue: When I try to use "==" It will not display today's appointments or any appointment. However, If I use ">=", It will show today and upcoming appointments. This is great but I do not need it for tomorrow's appointments. I want tomorrow to be separate.
I did notice I am using DateTime which I do have Dates with time stored in my variable.
I know If I need to get today's appointments I want to do something like this:
StartDateTimeBooking >= YESTERDAY_MIDNIGHT && StartDateTimeBooking <= TODAY_MIDNIGHT
My Problem is my time is in 24 hours' time. What equation or code do I need today to ensure that: Today, past, and upcoming appointments will work?
I know I am very close to the solution but any help would be greatly appreciated.
UPDATE: Is this logic correct?
This gives me todays list of appointments:
.Where(e => e.StartDateTimeBooking >= today && e.StartDateTimeBooking < today.AddDays(1))
This gives me tomorrows list of appointments only:
Where(e => e.StartDateTimeBooking > today.AddDays(1) && e.StartDateTimeBooking < today.AddDays(2))
This gives me an upcoming list of appointments
.Where(e => e.StartDateTimeBooking >= today)
This gives me past appointments:
.Where(e => e.StartDateTimeBooking < today)

Because dates include times in the database, you need an in between filter on your date:
Assuming today is your date variable and represents a date at midnight (e.g. DateTime.Today):
.Where(e => e.StartDateTimeBooking >= today && e.StartDateTimeBooking < today.AddDays(1))
This creates the between filter you should need. It's midnight or after, but before tomorrow at midnight (AddDays(1)).

Related

How to compare date value only in LINQ

I am trying to get the records from database where StartTime field should be today's date.
service.GetAll().Where(o => o.StartTime. == DateTime.Today.Date).Select(o => new SelectableItem(o.Id, o.TestPurpose, v == o.Id))
The date in database is of this format.
2016-07-01 07:00:00.000
How do I compare this format with today's date, I need to compare only date and not the time.
You can use approach specified by #Renan Araujo.
Or another way is, define two dates and use
.Where(o => o.StartTime >= date1 && o.StartTime < date2)
where
date1 = DateTime.Today.Date; // (lets say today's date=10-13-2016 )
date2 = DateTime.Today.AddDays(1).Date; // (tomorrow's date = 10-14-2016)
Use EntityFunctions.TruncateTime to remove the time portion:
service.GetAll()
.Where(o => EntityFunctions.TruncateTime(o.StartTime) == EntityFunctions.TruncateTime(DateTime.Today.Date))
.Select(o => new SelectableItem(o.Id, o.TestPurpose, v == o.Id))

Linq statement distinct not working on dates

I've been looking all over stackoverflow.com and the Interwebz to find out how to use Linq with Distinct(), but I'm not having any luck with my situation.
What I'm trying to do is show a list of dates (Aug 2015, July 2015, etc) with each date showing just once.
What happens is that the months are duplicated because you can publish a new blog post more than once in a month. I thought using Distinct would help, but it seems like it's not doing anything. When I try adding GroupBy(), my OrderByDescending stops working, and I'm not seasoned enough to simply turn this into an IList, which I've seen in a couple other examples.
BlogRepeater.DataSource = _PostRepository.GetAll(ConfigurationManager.GetSiteID())
.Where(x => x.DatePublished != null && x.DatePublished >= DateTime.Now.AddYears(-1))
.Distinct().OrderByDescending(x => x.DatePublished)
.Select(x => x.DatePublished.Value.Date);
What is the best way to be doing this?
I've tried taking pieces from other examples, to no avail. Thanks in advance.
UPDATE: Thanks for the help! Here is working code in hopes it can help someone else in the future.
Code Behind:
BlogRepeater.DataSource =
_PostRepository
.GetAll(ConfigurationManager.GetSiteID())
.Where(x => x.DatePublished != null && x.DatePublished >= DateTime.Now.AddYears(-1) && x.Status == "Published")
.Select(x => x.DatePublished.Value.ToString("MMM yyyy"))
.Distinct()
.OrderBy(x => x);
BlogRepeater.DataBind();
Front End:
<%#(Container.DataItem)%>
If your DatePublished field contains DateTime values with different times, the .Distinct() will not behave how you expect it to, because those values are essentially different.
If you want distinct dates, not date/times, then you can move the last .Select before the .Distinct():
BlogRepeater.DataSource =
_PostRepository
.GetAll(ConfigurationManager.GetSiteID())
.Where(x => x.DatePublished != null && x.DatePublished >= DateTime.Now.AddYears(-1))
.Select(x => x.DatePublished.Value.Date)
.Distinct()
.OrderByDescending(x => x);
If you want to find the distinct months, not dates, then you have to change the
.Select(x => x.DatePublished.Value.Date)
line to
.Select(x => x.DatePublished.Value.ToString("MMM yyyy"))
Feel free to change the "MMM yyyy" format to anything else you find suitable.

linq select where between dates

I'm trying to add to the dates all the events between Date and DateFinal in order to fill the calendar with the events.
I've already searched but I can't find any solution for this.
pageItems.Add("dates", allEvents.Select(i => i.Date).ToList());
This is what I have so far but only show the days of i.Date and I want to show all of the days between Date and DateFinal.
Cheers and thanks in advance
In the allEvents I have
allEvents = Current.Descendants(n => n.NodeTypeAlias == "EventPage")
.get_Items()
.Select(n => new{
Node = n,
Date = (Helper.ParseXmlDate(n.GetProperty("itemDate")) ?? n.UpdateDate).DatePart(),
DateFinal = (Helper.ParseXmlDate(n.GetProperty("itemDateFinal")) ?? n.UpdateDate).DatePart()
});
Use this:
allEvents.Where(i => i.Date > Date && i.Date < DateFinal).Select(i => i.Date).ToList()
First.. Sorry if I have misunderstood the question
If you have 2 DateTime and you want to select a list of all the Days(as DateTime) between those 2 dates, you could use Enumerable.Range using the amount of days between the Date and DateFinal to loop in your select statement to add a day to the start date and output a list of DateTimes
This will select all the dates between Date and DateFinal.
allevents.Select(i => Enumerable.Range(1, (i.DateFinal - i.Date).Days).Select(dayCount => i.Date.AddDays(dayCount))).ToList()
If you need to include Date and DateFinal to the list you can use
allevents.Select(i => Enumerable.Range(0, 1 + (i.DateFinal - i.Date).Days).Select(dayCount => i.Date.AddDays(dayCount))).ToList()
Input:
Date: 02/20/2013
DateFinal: 02/31/2013
OutPut:
02/20/2013
02/21/2013
02/22/2013
02/23/2013
...
Is that what you mean?
You probably searching for:
TimeSpan span=d2-d1;
span.TotalDays;
so it should look like:
allEvents.Select(i => (DateFinal - i.Date).TotalDays).ToList()
This shows all days between some DateFinal and i.Date
If this is not what you're searching for, please clarify.

Getting all orders that are from this month

Here my current month:
model.SalesForMonth = orders.Where(o => o.DateOfPayment.Value.Month == DateTime.Now.Month)
.Select(o => o.Total)
.Sum();
This is not working as expect as it's also fetching orders that happened last year at the same month.
Sure I could compare year and month, but there must be a more expressive solution I'm not familiar with.
How can I do this cleanly using Linq? (Not sure if relevant but orders is an IQueryable from Entity Framework)
The simplest way would be to create a start and end point:
// TODO: Consider what time zone you want to consider the current date in
var today = DateTime.Today;
var start = new DateTime(today.Year, today.Month, 1);
var end = start.AddMonths(1); // Exclusive end-point
var query = orders.Where(o => o.DateOfPayment.Value >= start &&
o.DateOfPayment.Value < end)
.Sum(o => o.Total)
I'm not sure what you want. You must compare year too to be sure that orders are from this year.
I think you can do it this way with linq:
model.SalesForMonth = orders.Where(o => (o.DateOfPayment.Value.Month == DateTime.Now.Month
&& o.DateOfPayment.Value.Year == DateTime.Now.Year))
.Select(o => o.Total)
.Sum();

LINQ - How to query a range of effective dates that only has start dates

I'm using C# 3.5 and EntityFramework. I have a list of items in the database that contain interest rates. Unfortunately this list only contains the Effective Start Date. I need to query this list for all items within a range.
However, I can't see a way to do this without querying the database twice. (Although I'm wondering if delayed execution with EntityFramework is making only one call.) Regardless, I'm wondering if I can do this without using my context twice.
internal IQueryable<Interest> GetInterests(DateTime startDate, DateTime endDate) {
var FirstDate = Context.All().Where(x => x.START_DATE < startDate).Max(x => x.START_DATE);
IQueryable<Interest> listOfItems = Context.All().Where(x => x.START_DATE >= FirstDate && x.START_DATE <= endDate);
return listOfItems;
}
If you could use a LINQ query, you can use let to do this:
(from c in dbContext.Table
let firstdate = dbContext.Table.Max(i => c.StartDate < startDate)
where c.StartDate >= firstdate
and c.StartDate <= enddate
select c)
I'm not sure if the max will work this way, so you may need to alternatively do:
(from c in dbContext.Table
let firstdate = dbContext.Table.Select(i => i.StartDate).Max(i => c.StartDate < i)
where c.StartDate >= firstdate
and c.StartDate <= enddate
select c)
Something like that.
I haven't tried this on EF but on Linq to objects it works fine:
var result = source
.OrderBy(x => x.start)
.GroupBy(x => x.start < startDate)
.SelectMany((x, i) => i == 0 ? new[] {new { value = x.Last().value, start = x.Last().start }} : x.Where(y => y.start < endDate));
The issue is that C# LINQ is missing an operator which gives you access to the previous item in a sequence. F# apparently can handle this. Workarounds involved either a GroupBy or an Aggregate operation. In this case, GroupBy can handle it.
It's not pretty and I wouldn't recommend using it over the two phase approach.

Categories