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();
Related
I am currently working with real-estate data, and each Listing entity has a ListingDate and a CloseDate. What I am currently trying to do is to count how many Listings are active in a given month and year (group by year and month).
So for an example if Listing1 had an ListingDate of 05/01/2020 and a CloseDate of 08/01/2020, there would be 1 Active count for May, June, July, and August and a year total of 4.
I am using EF and LINQ, and was wondering if I could solve it somehow.
Any help or advice is appreciated.
Sure you can; if you map listings to each month in which it's active, you can then simply group the results by month and get the counts trivially. Thus, the trickiest part is to just come up with the month DateTime values, which isn't that tricky.
Extension method to get month DateTimes from a start and end date:
public static IEnumerable<DateTime> GetMonths(this DateTime startDate, DateTime endDate)
{
var monthDiff = (endDate.Month - startDate.Month) + (12 * (endDate.Year - startDate.Year));
var startMonth = new DateTime(startDate.Year, startDate.Month, 1);
return Enumerable.Range(0, monthDiff + 1)
.Select(i => startMonth.AddMonths(i));
}
Create lookup:
var listingsByMonth = listings
.SelectMany(l =>
{
return l.ListingDate.GetMonths(l.ClosingDate.AddDays(-1)) // assuming closing date is exclusive
.Select(dt => new KeyValuePair<DateTime, Listing>(dt, l));
})
.ToLookup(kvp => kvp.Key, kvp => kvp.Value);
Demonstration of results:
foreach(var g in listingsByMonth)
{
Console.WriteLine($"{g.Key:yyyy-MM}: {g.Count()}");
}
Fiddle
Let's assume that date is given in DateTime structs. (You can parse text input to DateTime, check this) We can iterate over a List containing Listing entities, and perform a check to see if given date is in the range of ListingDate and ClosingDate. If the check succeeds, copy the entity to another list.
DateTime query = ...;
List<Listing> list = ...;
List<Listing> pass = new();
foreach (Listing entity in list)
{
if (entity.ListingTime < query && query < entity.ClosingTime)
pass.Add(entity)
}
While checking whether the query is in range, we could've used DateTime.Compare() but less than/greater than operators make the statement easier to read.
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)
I have data in my database that contains the following filed.
Id | name | RegDate
1 John 2014-09-05
2 mike 2014-09-05
3 Duke 2014-10-14
I'm performing a query to count the number of values where the reg date is equal 09. 09 is the month of the date.
I'm trying to convert the date I store in db in a month format then get a new month of a system date to get the result.
Here is my query in linq but it keeps on giving the wrong count. please I need your help. thanks.
var CountPassengers = (from c in db.CountPassengerManifestViews where c.DepartureDate.Month.ToString()== DateTime.Now.AddMonths(-1).ToString("MM") select c).Count();
I would strongly recommend that you get rid of all the string manipulation. Your query doesn't conceptually have anything to do with strings, so why are you introducing them into the code?
You can write your query as:
int currentMonth = DateTime.Today.AddMonths(-1).Month;
var passengerCount = db.CountPassengerManifestViews
.Count(c => c.DepartureDate.Month == currentMonth);
However, that will only filter by month - it won't filter by month and year, so if you have data from 2013 that would be included too. It's more likely that you want something like:
DateTime oneMonthAgo = DateTime.Today.AddMonths(-1);
DateTime start = oneMonthAgo.AddDays(1 - oneMonthAgo.Day);
DateTime end = start.AddMonths(1);
var passengerCount = db.CountPassengerManifestViews
.Count(c => c.DepartureDate >= start &&
c.DepartureDate < end);
That way you're expressing a range of dates, rather than just extracting the month part.
where c.DepartureDate.Month == DateTime.Now.AddMonths(-1).Month
You don't compare string representation, because it's already converted into DateTime object, so it doesn't make sense to do it your way. This simple change should be enough.
I am not sure why you are doing the string manipulation but if you only want to compare the month part of the two dates then do the following:
where c.DepartureDate.Month== DateTime.Now.AddMonths(-1).Month
I think your code compares Month.ToString() that gives "9" with ToString("MM") that gives "09".
You could also improve by removing ".ToString()":
int lastMonth = DateTime.Now.AddMonths(-1).Month;
var CountPassengers = (from c in db.CountPassengerManifestViews where c.DepartureDate.Month == lastMonth select c).Count();
Regards
Try this
var CountPassengers = (from c in db.CountPassengerManifestViews
where c.DepartureDate.Month.ToString("MM")== DateTime.Now.AddMonths(-1).ToString("MM")
select c).Count();
var month = DateTime.Now.AddMonths(-1).Month;
var CountPassengers = db.CountPassengerManifestViews.Count(c => c.DepartureDate.Month == month);
Scenario:
I'm trying to populate the C# List with all the time in a day as shown in example below:
00AM to 23PM.
Could someone please help me whether this can be achieved from LINQ or similar?
Thanks.
Assuming you want the difference between two succesive values to be one second, you can use this query:
var result = Enumerable.Range(0, 23 * 3600).Select(x => TimeSpan.FromSeconds(x)).ToList();
The number 23 * 3600 stands for total number of seconds between 00:00 and 23:00. If you want to have values from minute to minute, use this:
var result = Enumerable.Range(0, 23 * 60).Select(x => TimeSpan.FromMinutes(x)).ToList();
DateTime date = new DateTime();
var result = Enumerable.Repeat(date, 24)
.Select((x, i) => x.AddHours(i).ToString("HH tt"));
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