c# get all dates from database that appear with current week - c#

trying to get all the dates from the db that are within the current week
i have email1DueDate, email2DueDate, email3DueDate
and i want to see if they are due to be sent within the current week

First you should calculate two DateTime values for the start of the week and the end of the week, you can do that like this (assuming Monday is the first day):
DateTime startOfWeek = DateTime.Today;
int delta = DayOfWeek.Monday - startOfWeek.DayOfWeek;
startOfWeek = startOfWeek.AddDays(delta);
DateTime endOfWeek = startOfWeek.AddDays(7);
next you can use this in your LINQ query to get the results you need, I am assuming you want results to be rows that have any of your due dates fall in the week:
var results = DB.Table.Where(x =>
(x.email1DueDate >= startOfWeek && x.email1DueDate < endOfWeek) ||
(x.email2DueDate >= startOfWeek && x.email2DueDate < endOfWeek) ||
(x.email3DueDate >= startOfWeek && x.email3DueDate < endOfWeek)
);
If this is not what you need then you will need to clarify your requirements

LINQ
listOfDates.Where(x => x.email1DueDate > beginOfWeekDate && x.email1DueDate < endOfWeekDate).ToList();
Of course you'll still have to figure out the begin and end dates

Related

Optimizing date comparison query in Entity Framework

I am trying to optimize one of our most important queries and I would like to have some extra insights on how Entity Framework translates certain LINQ expressions.
I am using the repository pattern so my service layer (where I define my queries) is unaware of the actual data layer, which (currently) limits me to using only Where statements. Using joins and other constructs may help but that would require a rewrite of certain parts of the application. I'd like to exhaust all other options first before considering that.
I have come up with 3 variants of my query:
// Takes about 1900-2200ms for 120 records
public Expression<Func<Appointment, bool>> FilterByResources(DateTime startDate, DateTime endDate, IEnumerable<int> resourceIds)
{
// Appointments are filtered on the scheduler's start date, end date and the resources in the current page
Expression<Func<Appointment, bool>> filter = (x) => x.Assignments.Any(z => resourceIds.Contains(z.ResourceId))
&&
// Appointment starts somewhere between the start and end date
((DbFunctions.TruncateTime(x.StartDate).Value >= startDate && DbFunctions.TruncateTime(x.StartDate).Value <= endDate) ||
// Appointment started earlier than start date but ends earlier than end date
(DbFunctions.TruncateTime(x.EndDate).Value >= startDate && DbFunctions.TruncateTime(x.EndDate).Value <= endDate) ||
// Appointment starts and ends outside the boundaries
(DbFunctions.TruncateTime(x.StartDate).Value <= startDate && DbFunctions.TruncateTime(x.EndDate).Value >= endDate));
return filter;
}
Alternative #2:
// Takes about 2100ms for 120 records
public Expression<Func<Appointment, bool>> FilterByResources2(DateTime startDate, DateTime endDate, IEnumerable<int> resourceIds)
{
DateTime truncatedStartDate = startDate.Date;
DateTime truncatedEndDate = endDate.EndOfDay(); // Extension method that formats the time to 23:59:59
// Appointments are filtered on the scheduler's start date, end date and the resources in the current page
Expression<Func<Appointment, bool>> filter = (x) => x.Assignments.Any(z => resourceIds.Contains(z.ResourceId)) && (
(x.StartDate >= truncatedStartDate && x.StartDate <= truncatedEndDate) || // Appointment starts somewhere between the start and end date
(x.EndDate >= truncatedStartDate && x.EndDate <= truncatedEndDate) || // Appointment started earlier than start date but ends earlier than end date
(x.StartDate <= truncatedStartDate && x.EndDate >= truncatedEndDate) // Appointment starts and ends outside the boundaries
);
return filter;
}
Alternative 3:
// Takes about 1900ms for 120 records
public Expression<Func<Appointment, bool>> FilterByResources(DateTime startDate, DateTime endDate, IEnumerable<int> resourceIds)
{
DateTime truncatedStartDate = startDate.Date;
DateTime truncatedEndDate = endDate.EndOfDay(); // Extension method that formats the time to 23:59:59
// Appointments are filtered on the scheduler's start date, end date and the resources in the current page
Expression<Func<Appointment, bool>> filter = (x) => x.Assignments.Any(z => resourceIds.Contains(z.ResourceId)) && (
(x.StartDate.CompareTo(truncatedStartDate) >= 0 && x.StartDate.CompareTo(truncatedEndDate) <= 0) || // Appointment starts somewhere between the start and end date
(x.EndDate.CompareTo(truncatedStartDate) >= 0 && x.EndDate.CompareTo(truncatedEndDate) <= 0) || // Appointment started earlier than start date but ends earlier than end date
(x.StartDate.CompareTo(truncatedStartDate) <= 0 && x.EndDate.CompareTo(truncatedEndDate) >= 0) // Appointment starts and ends outside the boundaries
);
return filter;
}
A little explanation about this query: This query retrieves a list of appointments for a number of resources (i.e. people) between two dates. Because of that range, I need to include those records that start earlier, finish later or last longer than the range (hence the 3 expressions).
I tried switching the order of the expressions but the results remain stable. On average it takes between 1800ms and 2200ms for the entire web api call (I use postman for my tests)
So my question is how this query can be optimized? I think the date comparison expressions take the longest time but it may as well be the Any/Contains combination that slows down the query.

Daterange with startDate and endDate not working if both date same

I get the data returned of the selected date range which is between the range or isnt. but not if the startDate and endDate is the same. Like example: from 14.10.2017 - 14.10.2017. It returns me then no data (but it should because 5 database records are affected)
foreach (Content content in db.Contents)
{
if (content.ShippedDate < startDate || content.ShippedDate > endDate)
}
Anyone has a solution?
You should update the condition to include the same date.
1.1.2016 < 1.1.2016 //FALSE
1.1.2016 <= 1.1.2016 //TRUE
Adjusting conditions:
content.ShippedDate <= startDate
content.ShippedDate >= endDate
Code:
foreach (Content content in db.Contents)
{
if (content.ShippedDate <= startDate || content.ShippedDate >= endDate)
//the code here
}
use <= (smaller than or equal) and >= (greater than or equal) instead of < and >, this will match values that are equal as well rather than just the ones that are smaller or greater than given value.
Also please refer to this page to learn more about c# operators as this is a very basic questions
https://msdn.microsoft.com/en-us/library/6a71f45d.aspx

How to compare just month and day from a datetime object

In my C# program I have run into an obstacle where I have a table that stores date ranges (columns are date range ID (int), begin date (DateTime) and end date (DateTime). I want to query the table and get back rows that only fall within a specific date range. I cannot use datetime.date since that includes the year.
So for example, I want to query the table and get all date ranges that fall between 01-01 and 5-31.
I have tried using the following lambda to query the table, but my result set is empty.
List<DateRanges> tempDateRangeList = dataContext
.DateRanges
.Where(r=>r.BeginDate.Month <= startDate.Month
&& r.EndDate.Month >= finishDate.Month)
.ToList();
tempDateRangeList = tempDateRangeList.Where(r=>r.BeginDate.Day <= startDate.Day
&& r.EndDate.Day >= finishDate.Day)
.ToList();
Does anyone have any suggestions on how I could accomplish this?
Edit:
Examples of BeginDate and EndDate would be a list such as follows:
BeginDate 1/1/2016, 5/25/2016, 9/11/2016
EndDates 5/24/2016, 9/10/2016, 12/31/2016
Filter date would be:
startDate = 12/8
finishDate = 12/12
Expected result:
Begin Date of 9/11
End date of 12/31
There are two cases in your condition - month equal to boundary month, in which case you must test day number, and a different month, in which you ignore day. Hence the query:
List<DateRanges> tempDateRangeList =
dataContext.DateRanges.Where(r =>
((r.BeginDate.Month < startDate.Month) ||
(r.BeginDate.Month == startDate.Month && r.BeginDate.Day <= startDate.Day)) &&
((r.EndDate.Month > finishDate.Month) ||
(r.EndDate.Month == finishDate.Month) && r.EndDate.Day >= finsihDate.Day))
.ToList();
Condition is ugly and very hard to follow but covers all cases. This query returns all records which define date ranges that completely fall under the boundary dates.
If you wish to find records that are just overlapping (completely or partially) with the filtering range, then the query would be:
List<DateRanges> tempDateRangeList =
dataContext.DateRanges.Where(r =>
((r.BeginDate.Month < endDate.Month) ||
(r.BeginDate.Month == endDate.Month && r.BeginDate.Day <= endDate.Day)) &&
((r.EndDate.Month > startDate.Month) ||
(r.EndDate.Month == startDate.Month) && r.EndDate.Day >= startDate.Day))
.ToList();
This condition may bend your mind, but it works fine.
If a lambda expression isn't compulsory, I've used linq queries (because it was the first solution i've thought).
var validRanges = from range in ranges
where range.BeginDate.CompareTo(startDate) <= 0
where range.EndDate.CompareTo(endDate) >= 0
select range;
Using CompareTo is the easiest way to compare two DateTime struct.
I invite you to take a look here for a complete description of the method.
Edit
If you aren't interested in hours of your dates, but only in Day and Month, you should use range.BeginDate.Date.CompareTo(startDate.Date) and range.EndDate.Date.CompareTo(endDate.Date)

Find total number of days within a range using Linq

I have to find a 0-30 days range based on date sent value. It needs to be calculated against currentDate. I've done the below code. I need to confirm if it is correct.
query = query
.Where(x => (int)(EntityFunctions.DiffDays(currentDate, (DateTime)x.DATE_SENT)) >= 0
&& (int)(EntityFunctions.DiffDays(currentDate, (DateTime)x.DATE_SENT)) <= 30);
Your valuable suggestion is most welcome.
You can create an Enumerable Range:
DateTime start = DateTime.Now; // Or an other date
DateTime end = start.AddDays(30);
var DateRange = Enumerable.Range(0, 1 + end.Subtract(start).Days)
.Select(offset => start.AddDays(offset))
.ToArray();

Comparing times without date?

I am having trouble comparing times.
From what I have researched it most likely is due to the time not having a date.
My code,
This gets a dateTime value from the database.
var getDateTime = sql.Staff_Time_TBLs.Where(p => p.Staff_No ==
SelectedEmployee.Key && p.Date_Data == day).Select(p => p.Time_Data_1).ToList();
DateTime dateTimeGet = Convert.ToDateTime(getDateTime);
dateTimeGet returns a value like this "2012/12/12 15:03:00.000"
I then declare variables to hold the time.
TimeSpan startCompare = TimeSpan.Parse("15:00");
TimeSpan endCompare = TimeSpan.Parse("21:00");
Then comparing the values Compare DateTime
if ((endCompare > dateTimeGet) && (startCompare < dateTimeGet))
{
//match found
}
I am getting a compile error,
operands cannot be given to to type timespan and datetime
How do I compare times in this situation?
Just edit your code like this:
if ((endCompare > dateTimeGet.TimeOfDay) && (startCompare < dateTimeGet.TimeOfDay))
{
//match found
}
You could create DateTime values instead of TimeSpan to compare the value, using the Date of your db time:
DateTime startCompare = dateTimeGet.Date.AddHours(15);
DateTime endCompare = dateTimeGet.Date.AddHours(21);
if ((endCompare > dateTimeGet) && (startCompare < dateTimeGet))
{
// match found
}
In the example you showed, actually would be enough to compare the Hour part of dateTimeGet:
if (dateTimeGet.Hour >= 15 && dateTimeGet.Hour <= 21)
// match found
Actually you are comparing time with date in endCompare > dateTimeGet so you are getting the error
operands cannot be given to to type timespan and datetime
To compare time-span you need to extract the time from date in dateTimeGet by simply using TimeOfDay.
if ((endCompare > dateTimeGet.TimeOfDay) && (startCompare < dateTimeGet.TimeOfDay))
{
//match found
}
This will convert the date into time. For more details about TimeOfDayclick here Hope this works fine for you.
The issue is that, as you rightly say, you are comparing dates to times
A time-span is a measurement of time measured in Hours, where as a date-time is a measurement of time measured in days
so 2012/12/12 15:03:00.000 is approximately 735248.625 days or 17645967 hours
which you are then comparing to a timespan of 15 hours
so you need to either add 735248 days to your time span or drop 735248 days form your Date
both can be easily done
If you call the time TimeOfDay property on the date it will ignore the days and just return 0.625 days as 15 hours
Which means your code would look like this
if ((endCompare > dateTimeGet.TimeOfDay ) && (startCompare < dateTimeGet.TimeOfDay))
OR
If you add the time span to the at midnight date it will create the correct date time for comparation
Which means your code would look like this
if ((dateTimeGet.Date + endCompare > dateTimeGet ) && (dateTimeGet.Date + startCompare < dateTimeGet.TimeOfDay))

Categories

Resources