Lambda between two dates explicit - c#

I am in need of some wizards.
I have a table
Start End PersonID
-----------------------------------------------------
10/07/2017 00:00:00 18/07/2017 00:00:00 1
27/07/2017 00:00:00 27/07/2017 00:00:00 1
28/07/2017 00:00:00 28/07/2017 00:00:00 1
29/07/2017 00:00:00 29/07/2017 00:00:00 1
30/07/2017 00:00:00 30/07/2017 00:00:00 1
If I search for
Date Start = 11/07/2017
Date End = 12/07/2017
Using this query:
DateTime start = new DateTime(2017,07,11,0,0,0,0,0);
DateTime end = start.AddDays(1);
DateTime[] days = new DateTime[end.Subtract(start).Days];
for (int i = 0; i < end.Subtract(start).Days; i++)
{
var d = start.AddDays(i);
days[i] = d;
}
IQueryable block = tmOpen1.Calendar.Where(x => days.All(y => y >= x.start && y <= x.end)).Select(x => new { ID = x.PersonID });`
I get a positive result for ROW 1 (10/07/2017 - 18/07/2017)
However If I apply it against the remaining rows e.g. Filter
Date Start = 28/07/2017
Date End = 29/07/2017
Then obviously this will fail. How Can I get this side of the search to work.
E.g. Either
Take the first row and make it split out into individual rows
Make the Individual rows return true if a Person has several true conditions.
I hope one of the geniuses here can help.

Seems like all you really need is something like this:
DateTime start = new DateTime(2017,07,11,0,0,0,0,0);
DateTime end = start.AddDays(1);
var results = tmOpen1.Calendar
.Where(c => start <= c.end && end >= c.start)
.Select(x => new { ID = x.PersonID });

If your interval starts or ends somewhere between a start and end date from the table, than it means it is overlapping and you should included in your result.
tmOpen1.Calendar.Where(x => (startDate >= x.start && startDate <= x.end) || (endDate >= x.start && endDate <= x.end)).Select(x => new { ID = x.PersonID });
So an interval 10.07 - 27.07 should give you the first 2 rows, right?
Or is the interval supposed to be fully enclosed between 2 dates in the table?

From understanding of your question you want to know when the Date Start or Date End is within a range of dates.
You can check Date Start is within the date range or the Date End is within the date range
Example:
List<DateRange> dates = new List<DateRange>();
dates.Add(new DateRange()
{
StartDate = new DateTime(2017, 07, 10),
EndDate = new DateTime(2017, 07, 18)
});
dates.Add(new DateRange()
{
StartDate = new DateTime(2017, 07, 28),
EndDate = new DateTime(2017, 07, 28)
});
DateRange search1 = new DateRange()
{
StartDate = new DateTime(2017, 07, 11),
EndDate = new DateTime(2017, 07, 12)
};
DateRange search2 = new DateRange()
{
StartDate = new DateTime(2017, 07, 28),
EndDate = new DateTime(2017, 07, 29)
};
var result1 = dates.Where(x => search1.StartDate >= x.StartDate && search1.StartDate <= x.EndDate ||
search1.EndDate <= x.StartDate && search1.EndDate >= x.EndDate);
var result2 = dates.Where(x => search2.StartDate >= x.StartDate && search2.StartDate <= x.EndDate ||
search2.EndDate <= x.StartDate && search2.EndDate >= x.EndDate);

Simplier with the not valid time frame:
DateTime start = new DateTime(2017, 07, 11, 0, 0, 0, 0, 0);
DateTime end = start.AddDays(1);
var results = tmOpen1.Calendar.
.Where( c => ! ( c.Start > end || c.End < start) )
.Select(x => new { ID = x.PersonID } );
For DateTime start = new DateTime(2017, 07, 11, 0, 0, 0, 0, 0);
The result are:
TEST 1: 11/07/2017 00:00:00
Start:10/07/2017 00:00:00 End:18/07/2017 00:00:00 ID:1
For DateTime start = new DateTime(2017, 07, 28, 0, 0, 0, 0, 0);
The result are:
TEST 2: 28/07/2017 00:00:00
Start:28/07/2017 00:00:00 End:28/07/2017 00:00:00 ID:1
Start:29/07/2017 00:00:00 End:29/07/2017 00:00:00 ID:1

modelclassList= modelclassList.Where(x => x.gf_expdate>DateTime.Now).ToList();
to check expiry date and save back list of model class

Related

Do not include 2nd date range in 1st date range

DateTime startDate1 = (DateTime)StartDate;
DateTime endDate1 = (DateTime)EndDate;
DayOfWeek? day = db.DayOfWeek;
var dayCount = dates.Count(x => x.DayOfWeek == day);
List<DateTime> dates =
Enumerable.Range(0, (int)((EndDate - StartDate).TotalDays) + 1)
.Select(n => StartDate.AddDays(n))
.ToList();
DateTime startDate1 = new DateTime(2018, 11, 01);
DateTime endDate1 = new DateTime(2018, 11, 30);
DateTime startDate2 = new DateTime(2018, 11, 25);
DateTime endDate2 = new DateTime(2018, 11, 30);
if ((startDate2 >= startDate1 && startDate2 <= endDate1) ||
(endDate2 >= startDate1 && endDate2 <= endDate1))
I want to count the number DayOfWeek inside of the range startDate1 and endDate1 and exclude startDate2 and endDate2 from that range completely.
In the example ranges above, my current code return '4' Mondays when I want it to return '3'.
Let's say the endDate1 is now (2018, 12, 31) and the rest of the dates are the same, it should return a count of '8' for Monday instead of the '9'.
Basically, I want to exclude the (2) range from the count regardless if it is within/overlaps the (1) range. How would I go about this?

how to create range datetime for data without switch in c#?

i get onlinedata,i want show in cells base Specified time,datetime range is 9:00:00 to 13:00:00 and i want each 5 minute get data from onlinedata.i dont use switch or if-else
List<TradeDto> cMIMData = new List<TradeDto>();
cMIMData = (List<TradeDto>)data;
cMIMData have TradeDate,TradeDateTime,TradeTime,...,and value properties
your description was not good enough, must use while base on date by increase 5 min, you can use loop(while,for,...) and check online data with lambda expression
cMIMData = cMIMData.OrderByDescending(x => x.TradeDateTime).ToList();
startDate = new DateTime(currentDate.Year, currentDate.Month, currentDate.Day, 9, 5, 0);
endDate = new DateTime(currentDate.Year, currentDate.Month, currentDate.Day, 13, 0, 0);
while (startDate < endDate)
{
var value = cMIMData.Where(x => x.TradeDateTime.Date == your date && x.TradeTime >= startDate.AddMinutes(-5).TimeOfDay &&
x.TradeTime <= startDate.TimeOfDay).First(); //get last item value in Limit specified time
startDate = startDate.AddMinutes(5);
}

How to find exact date range from list of date ranges by entering single date

I want to find the date range which falls in input date, following is structure
public class Duration
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
var durations = new List<Duration>();
var duration1 = new Duration()
{
StartDate = new DateTime(2017, 08, 1),
EndDate = new DateTime(2017, 08, 10)
};
durations.Add(duration1);
var duration2 = new Duration()
{
StartDate = new DateTime(2017, 08, 5),
EndDate = new DateTime(2017, 08, 10)
};
durations.Add(duration2);
var duration3 = new Duration()
{
StartDate = new DateTime(2017, 08, 5),
EndDate = new DateTime(2017, 08, 6)
};
durations.Add(duration3);
Now I want to find duration which is closest to the entered date for list of <Durations> with LINQ or for-loop
My expected result for currentDate=new DateTime(2017, 08, 7); is duration2
You first need to check if the currentDate is within the start and end dates of each range. For the ones that meet that condition, you calculate the "closeness" adding both distances. When you find one lapse(gap) smaller tan the previous, you save its index... and voilá
int lapse = Integer.MaxValue;
int counter = 0;
int index = 0;
foreach (d in durations) {
if (((d.StartDate <= currentDate) && (d.EndDate >= currentDate))) {
int newlapse = ((currentDate - d.StartDate).TotalDays + (d.EndDate - currentDate).TotalDays);
if ((newlapse < lapse)) {
lapse = newlapse;
index = counter;
}
}
counter +=1;
}
return durations(index);
If you need the middle of interval to be closest:
durations.OrderBy((d) => Math.Abs(d.EndDate.Ticks + d.StartDate.Ticks) / 2 - currentDate.Ticks).FirstOrDefault();
If you need the start of interval to be closest:
durations.OrderBy((d) => Math.Abs(d.EndDate.Ticks - currentDate.Ticks)).FirstOrDefault();
As D le mentioned above
First check if currentDate is within the start and end dates
Second select the duration with the minimal difference between start end end date
I used a nuget package called morelinq which gives nice extensions methods like MinBy:
var result = (from d in durations
where (d.StartDate <= currentDate && d.EndDate >= currentDate)
select d).MinBy(d => d.EndDate - d.StartDate);

Linq to Entity Birthday Comparison

I have the requirement to create a query using Linq to Entities where the birthday must fall within 2 days ago and the next 30 days.
The following returns nothing:
DateTime twoDaysAgo = DateTime.Now.AddDays(-2);
int twoDaysAgoDay = twoDaysAgo.Day;
int twoDaysAgoMonth = twoDaysAgo.Month;
DateTime MonthAway = DateTime.Now.AddDays(30);
int monthAwayDay = MonthAway.Day;
int monthAwayMonth = MonthAway.Month;
var bdays = from p in db.Staffs where EntityFunctions.TruncateTime(p.BirthDate) > EntityFunctions.TruncateTime(twoDaysAgo) &&
EntityFunctions.TruncateTime(p.BirthDate) < EntityFunctions.TruncateTime(MonthAway)
orderby p.BirthDate select p;
return bdays;
The problem I'm having is that I need something where if the birthday falls from 11/3 to 12/5, it should return it. The reason it fails because the birthdays include the Year. However, when I use something like:
p.BirthDate.Value.Month
I receive the error that this isn't support with Linq to Entities. Any assistance would be appreciated.
Year-wrapping independent solution:
void Main()
{
var birthdays = new List<DateTime>();
birthdays.Add(new DateTime(2013, 11, 08));
birthdays.Add(new DateTime(2012, 05, 05));
birthdays.Add(new DateTime(2014, 05, 05));
birthdays.Add(new DateTime(2005, 11, 08));
birthdays.Add(new DateTime(2004, 12, 31));
foreach(var date in birthdays.Where(x => x.IsWithinRange(twoDaysAgo, MonthAway))){
Console.WriteLine(date);
}
}
public static class Extensions {
public static bool IsWithinRange(this DateTime #this, DateTime lower, DateTime upper){
if(lower.DayOfYear > upper.DayOfYear){
return (#this.DayOfYear > lower.DayOfYear || #this.DayOfYear < upper.DayOfYear);
}
return (#this.DayOfYear > lower.DayOfYear && #this.DayOfYear < upper.DayOfYear);
}
}
Output with
DateTime twoDaysAgo = DateTime.Now.AddDays(-2);
DateTime MonthAway = DateTime.Now.AddDays(30);
8/11/2013 0:00:00
8/11/2005 0:00:00
Output with
DateTime twoDaysAgo = new DateTime(2012, 12, 25);
DateTime MonthAway = new DateTime(2013, 01, 05);
31/12/2004 0:00:00
If you want to ignore the value of the year, what about using DayOfYear function ?
var bdays = from p in db.Staffs
where EntityFunctions.DayOfYear(p.BirthDate) > EntityFunctions.DayOfYear(twoDaysAgo) &&
EntityFunctions.DayOfYear(p.BirthDate) < EntityFunctions.DayOfYear(MonthAway)
orderby p.BirthDate select p;
You can change all the years to now since year is irrelevant and then you can check it this way
DateTime twoDaysAgo = DateTime.Today.AddDays(-2);
DateTime monthAway = DateTime.Today.AddMonths(1);
List<DateTime> checkDates = new List<DateTime>
{ new DateTime(2011, 11, 3), new DateTime(2011, 12, 5), new DateTime(2011, 12, 6), new DateTime(2011, 11, 2) };
checkDates = checkDates.Select(x => new DateTime(DateTime.Today.Year, x.Month, x.Day)).ToList();
var bdays = from p in checkDates
where (p >= twoDaysAgo && p <= monthAway) ||
(p>= twoDaysAgo.AddYears(-1) && p <= monthAway.AddYears(-1))
orderby p
select p;
This results in
11/3/2013 12:00:00 AM
12/5/2013 12:00:00 AM
This also works with the following list of dates when today is new DateTime(2013, 12, 31)
List<DateTime> checkDates = new List<DateTime>
{ new DateTime(2011, 12, 29), new DateTime(2011, 12, 28), new DateTime(2011, 1, 30), new DateTime(2011, 2, 2) };
Giving the results
1/30/2013 12:00:00 AM
12/29/2013 12:00:00 AM
How about if you add the the nr. of years from the birthdate to today?
Something like:
(untested)
var now = DateTime.Now;
var twoDaysAgo = now.AddDays(-2);
var monthAway = now.Now.AddDays(30)
var bdays =
from p in db.Staffs
let bDay = EntityFunctions.AddYears(p.BirthDate,
EntityFunctions.DiffYears(now, p.BirthDate))
where
bDay > twoDaysAgo &&
bDay < monthAway
orderby p.BirthDate
select p;

Getting Overlapping Start and End Date

Given a DateRange I need to return a list of Start and EndDates that overlaps the given period.
what is the best way to do it? Thanks for your time in advance.
static void Main(string[] args)
{
//Period 1stMarch to 20th April
var startDate = new DateTime(2011, 03, 1);
var endDate = new DateTime(2011, 4, 20);
List<BookedPeriod> bookedPeriods=new List<BookedPeriod>();
bookedPeriods.Add(new BookedPeriod {StartDate = new DateTime(2011, 02, 5), EndDate = new DateTime(2011, 3, 15)});
bookedPeriods.Add(new BookedPeriod { StartDate = new DateTime(2011, 03, 20), EndDate = new DateTime(2011, 4, 10) });
bookedPeriods.Add(new BookedPeriod { StartDate = new DateTime(2011, 04, 01), EndDate = new DateTime(2011, 4, 15) });
List<OverlappedPeriod> myOverllappedPeriods = GetOverllapedPeriods(startDate, endDate, bookedPeriods);
}
public static List<OverlappedPeriod>GetOverllapedPeriods(DateTime startDate,DateTime endDate,List<BookedPeriod>bookedPeriods)
{
List<OverlappedPeriod>overlappedPeriods=new List<OverlappedPeriod>();
// Given a DateRange I need to return a list of Start and EndDates that overlaps
//??how I do i
return overlappedPeriods;
}
}
public class BookedPeriod
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
public class OverlappedPeriod
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
EDITED
I have decided to edit in the hope of clarifing and therefore helping who has to help me.
I get confused by overlapped vs intersect.
A scenario might help
I have booked a subscription to the gym that goes from 01 March 11 to 20 April 11
I go on holiday between 05 Feb 11 to 15 Mar 11
I need to get the start and end date when my subscription is valid that I will NOT BE GOING TO THE GYM
The result I should get back is StartDate=1 March 2011 EndDate =15 March 2011
myAttempt:
static void Main()
{
//Holiday Period
var startDate = new DateTime(2011, 02, 5);
var endDate = new DateTime(2011, 3, 15);
List<BookedPeriod> bookedPeriods = new List<BookedPeriod>();
bookedPeriods.Add(new BookedPeriod { StartDate = new DateTime(2011, 02, 5), EndDate = new DateTime(2011, 4, 20) });
List<OverlappedPeriod> overlappedPeriods=new List<OverlappedPeriod>();
foreach (var bookedPeriod in bookedPeriods)
{
DateTime newStartDate = new DateTime();
DateTime newEndDate = new DateTime();
OverlappedPeriod overlappedPeriod=new OverlappedPeriod();
overlappedPeriod.StartDate = newStartDate;
overlappedPeriod.EndDate = newEndDate;
GetDateRange(bookedPeriod.StartDate, bookedPeriod.EndDate, out newStartDate, out newEndDate);
overlappedPeriods.Add(overlappedPeriod);
}
//do something with it
}
private static void GetDateRange(DateTime startDate,DateTime endDate,out DateTime newStartDate,out DateTime newEndDate)
{
/*
* I need to get the start and end date when my subscription is valid that I will NOT BE GOING TO THE GYM
The result I should get back is StartDate=1 March 2011 EndDate =15 March 2011
*/
}
Are you looking for dates that are completely within the provided period, or only partially?
Completely within the range:
var overlapped =
from period in bookedPeriods
where period.StartDate >= startDate && period.EndDate <= endDate
select new OverlappedPeriod { StartDate = period.StartDate, EndDate = period.EndDate };
overlappedPeriods = overlapped.ToList();
Partially overlapping:
var overlapped =
from period in bookedPeriods
where (period.StartDate >= startDate && period.EndDate <= endDate)
|| (period.EndDate >= startDate && period.EndDate <= endDate)
|| (period.StartDate <= startDate && period.EndDate >= startDate)
|| (period.StartDate <= startDate && period.EndDate >= endDate)
select new OverlappedPeriod
{
StartDate = new DateTime(Math.Max(period.StartDate.Ticks, startDate.Ticks)),
EndDate = new DateTime(Math.Min(period.EndDate.Ticks, endDate.Ticks))
};
overlappedPeriods = overlapped.ToList();
this piece of LINQ might help:
var overlappedPeriods = bookedPeriods.Where(p=>p.EndDate > startDate && p.StartDate < endDate);
then transform the results accordingly to your OverlappedPeriod class
Something like this (not tested sorry):
return bookedPeriods.Where(
b => (b.StartDate > startDate && b.StartDate < endDate) ||
(b.EndDate> startDate && b.EndDate < endDate) ||
(b.StartDate < startDate && b.EndDate > endDate)
).ToList()
One method would be to make use of the Rectangle class to calculate intersects. So the procedure would be to create a rectangle for each date range then use the Rectangle.Intersect( ) method.

Categories