This question already has answers here:
Determine Whether Two Date Ranges Overlap
(39 answers)
Closed 4 years ago.
I am writing a scheduling program using an algorithm. At the last stage of the algorithm I need to look into the timetable (the timetable which was created) to see if the student is already assigned to a class at that time.
Therefore, we have:
Current Class Start Time: (2017, 02, 09, 10, 00, 00)
Current Class Finish Time: (2017, 02, 09, 11, 00, 00)
At this moment we will search into the timetable to see what other classes student A is assigned to:
For example, let's say on the same date they are already assigned to:
Class 'Z' Start Time: (2017, 02, 09, 09, 00, 00)
Class 'Z' Finish Time: (2017, 02, 09, 12, 00, 00)
Now I want to find the time range of Class 'Z' and compare it with the time range of Current Class.
DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);
DateTime StartCurrent = new DateTime(2017, 02, 09, 10, 00, 00);
DateTime StartCurrent = new DateTime(2017, 02, 09, 11, 00, 00);
if (They do not clash)
{
Assign
}
if (Clash)
{
Select Another Student
}
Could anyone please help me with my 'IF statements' and also how to solve this problem.
The way that I am thinking of it, there are three possibilities:
If 'current class' (Start and end time) lands in between 'Class Z' (Clash 1)
If the 'start time' of 'current class' lands in between 'Class Z' (Clash 2)
If the 'end time' of 'current class' lands in between 'Class Z' (Clash 3)
Thank You
This is the simplest way to do it:
public static bool HasOverlap(DateTime start1, DateTime end1, DateTime start2, DateTime end2)
{
return start1 < end2 && end1 > start2;
}
Or if the dates aren't necessarily in the correct start/end order:
public static bool HasOverlap(DateTime start1, DateTime end1, DateTime start2, DateTime end2)
{
return Min(start1, end1) < Max(start2, end2) && Max(start1, end1) > Min(start2, end2);
}
public static DateTime Max(DateTime d1, DateTime d2)
{
return d1 > d2 ? d1 : d2;
}
public static DateTime Min(DateTime d1, DateTime d2)
{
return d2 > d1 ? d1: d2;
}
Note, if a class ends at 2 and the next starts at 2 there will be no overlap. Since you're talking about classes, I'm assuming this is how you want it.
Testing your example:
static void Main(string[] args)
{
DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);
DateTime StartCurrent = new DateTime(2017, 02, 09, 10, 00, 00);
DateTime EndCurrent = new DateTime(2017, 02, 09, 11, 00, 00);
if(HasOverlap(startClassZ, endClassZ, StartCurrent, EndCurrent))
{
Console.WriteLine("clash");
}
else
{
Console.WriteLine("yay");
}
Console.Read();
}
I've added some quick tests for you:
public static void Test1()
{
// Class A overlaps class B
DateTime aStart = DateTime.Parse("2017-01-01T09:00:00");
DateTime aEnd = DateTime.Parse("2017-01-01T10:00:00");
DateTime bStart = DateTime.Parse("2017-01-01T09:30:00");
DateTime bEnd = DateTime.Parse("2017-01-01T11:00:00");
bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
Console.WriteLine($"1: {isCorrect}");
}
public static void Test2()
{
// Class A "surrounds" class B
DateTime aStart = DateTime.Parse("2017-01-01T09:00:00");
DateTime aEnd = DateTime.Parse("2017-01-01T15:00:00");
DateTime bStart = DateTime.Parse("2017-01-01T09:30:00");
DateTime bEnd = DateTime.Parse("2017-01-01T11:00:00");
bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
Console.WriteLine($"2: {isCorrect}");
}
public static void Test3()
{
// Class B "surrounds" class A
DateTime aStart = DateTime.Parse("2017-01-01T09:30:00");
DateTime aEnd = DateTime.Parse("2017-01-01T11:00:00");
DateTime bStart = DateTime.Parse("2017-01-01T09:00:00");
DateTime bEnd = DateTime.Parse("2017-01-01T15:00:00");
bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
Console.WriteLine($"3: {isCorrect}");
}
public static void Test4()
{
// Class A is before Class B
DateTime aStart = DateTime.Parse("2017-01-01T09:00:00");
DateTime aEnd = DateTime.Parse("2017-01-01T11:00:00");
DateTime bStart = DateTime.Parse("2017-01-01T11:00:00");
DateTime bEnd = DateTime.Parse("2017-01-01T12:00:00");
bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == false;
Console.WriteLine($"4: {isCorrect}");
}
public static void Test5()
{
// Class A is after Class B
DateTime aStart = DateTime.Parse("2017-01-01T12:00:00");
DateTime aEnd = DateTime.Parse("2017-01-01T14:00:00");
DateTime bStart = DateTime.Parse("2017-01-01T11:00:00");
DateTime bEnd = DateTime.Parse("2017-01-01T12:00:00");
bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == false;
Console.WriteLine($"5: {isCorrect}");
}
public static void Test6()
{
// Class B overlaps class A
DateTime bStart = DateTime.Parse("2017-01-01T09:00:00");
DateTime bEnd = DateTime.Parse("2017-01-01T10:00:00");
DateTime aStart = DateTime.Parse("2017-01-01T09:30:00");
DateTime aEnd = DateTime.Parse("2017-01-01T11:00:00");
bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
Console.WriteLine($"6: {isCorrect}");
}
static void Main()
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Console.Read();
}
You are offering three possibilities:
A) Whole currentClass is in zClass
B) Start of currentClass is in zClass
C) End of currentClass is in zClass
I would like to point out that A) means the same as B) and C) combined, thus does not need a special attention. Moreover, if you will try and draw a simplest sketch in your mind (or on paper) of duration of classes, then the conditions will pop themselves out quite naturally as:
clash = (endOfCurrentClass > startOfZClass) || (startOfCurrentClass < endOfZClass)
What remains is to think about equivalence (e.g. endOfCurrentClass == startOfZClass) but this depends on other constraints (does class-times incorporate pauses in between classes? Are they in a same room? ...). However this is another problem.
You need double check:
classZ with current in this case
DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);
DateTime startCurrent = new DateTime(2017, 02, 10, 10, 00, 00);
DateTime endCurrent = new DateTime(2017, 02, 09, 11, 00, 00);
and current with classZ
DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);
DateTime startCurrent = new DateTime(2017, 02, 08, 10, 00, 00);
DateTime endCurrent = new DateTime(2017, 02, 09, 13, 00, 00);
Full code is here:
DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);
DateTime startCurrent = new DateTime(2017, 02, 08, 10, 00, 00);
DateTime endCurrent = new DateTime(2017, 02, 09, 13, 00, 00);
bool ClashCurrentStart = startClassZ < startCurrent && startCurrent < endClassZ;
bool ClashCurrentEnd = startClassZ < endCurrent && endCurrent < endClassZ;
//bool ClashCurrentBetween = ClashCurrentStart && ClashCurrentEnd;
bool ClashClassZStart = startCurrent < startClassZ && startClassZ < endCurrent;
bool ClashClassZEnd = startCurrent < endClassZ && endClassZ < endCurrent;
//bool ClashClassZBetween = ClashClassZStart && ClashClassZEnd;
bool Clash = ClashCurrentStart || ClashCurrentEnd || ClashClassZStart || ClashClassZEnd;
if (!Clash)
{
//Assign
}
else // Clash
{
//Select Another Student
}
Related
I was trying to use this solution to count between two times in a csv file.
I tried:
var count = _ais.LoadRecords(Parameters.MinDate, Parameters.MaxDate)
.SkipWhile(record => DateTime.Parse(record.Time).Date != new DateTime(2016, 01, 01,08,00,00))
.TakeWhile(record => DateTime.Parse(record.Time).Date != new DateTime(2016, 01, 01, 09, 00, 00))
.Count();
where record.Time is:
public DateTime Time { get; set; }
The compiler points at record.Time and tells me:
Argument 1: cannot convert from 'System.DateTime' to 'System.ReadOnlySpan<char>'
Is there a way I can use time here?
You don't need to parse your record.Time property.
var count = _ais.LoadRecords(Parameters.MinDate, Parameters.MaxDate)
.SkipWhile(record => record.Time.Date != new DateTime(2016, 01, 01,08,00,00))
.TakeWhile(record => record.Time.Date != new DateTime(2016, 01, 01, 09, 00, 00))
.Count();
I have list of Appointment class.
In below code;
appointment1,appointment2 and appointment3 are intersect.
appointment4 and appointment5 are intersect.
appointment6 is non intersect
appointment1,appointment2 and appointment3 start datetime is '2018-07-10 08:00:00' and finish datetime is '2018-07-10 12:00:00' and total time is 4 hours here.
appointment4 and appointment5 start datetime is '2018-07-10 14:00:00' and finishdatetime is '2018-07-10 17:00:00' and total time is 3 hours here.
and appointment6 is non intersect comes 1 hour here.
And total time is 4+3+1=8,
How can i find 8 in given Appointment datetime values.
class Program
{
static void Main(string[] args)
{
List<Appointment> appointments = new List<Appointment>();
Appointment appointment1 = new Appointment();
appointment1.StartDate = new DateTime(2018, 07, 11, 08, 00, 00);
appointment1.FinishDate = new DateTime(2018, 07, 11, 11, 00, 00);
Appointment appointment2 = new Appointment();
appointment2.StartDate = new DateTime(2018, 07, 11, 10, 00, 00);
appointment2.FinishDate = new DateTime(2018, 07, 11, 12, 00, 00);
Appointment appointment3 = new Appointment();
appointment3.StartDate = new DateTime(2018, 07, 11, 09, 00, 00);
appointment3.FinishDate = new DateTime(2018, 07, 11, 12, 00, 00);
Appointment appointment4 = new Appointment();
appointment4.StartDate = new DateTime(2018, 07, 11, 14, 00, 00);
appointment4.FinishDate = new DateTime(2018, 07, 11, 16, 00, 00);
Appointment appointment5 = new Appointment();
appointment5.StartDate = new DateTime(2018, 07, 11, 15, 00, 00);
appointment5.FinishDate = new DateTime(2018, 07, 11, 17, 00, 00);
Appointment appointment6 = new Appointment();
appointment6.StartDate = new DateTime(2018, 07, 11, 18, 00, 00);
appointment6.FinishDate = new DateTime(2018, 07, 11, 19, 00, 00);
appointments.Add(appointment1);
appointments.Add(appointment2);
appointments.Add(appointment3);
appointments.Add(appointment4);
appointments.Add(appointment5);
appointments.Add(appointment6);
Console.ReadLine();
}
}
public class Appointment
{
public DateTime StartDate { get; set; }
public DateTime FinishDate { get; set; }
}
You first need to merge the overlapping times and then sum the timespan:
void Main()
{
List<Appointment> appointments = new List<Appointment>();
Appointment appointment1 = new Appointment();
appointment1.StartDate = new DateTime(2018, 07, 11, 08, 00, 00);
appointment1.FinishDate = new DateTime(2018, 07, 11, 11, 00, 00);
Appointment appointment2 = new Appointment();
appointment2.StartDate = new DateTime(2018, 07, 11, 10, 00, 00);
appointment2.FinishDate = new DateTime(2018, 07, 11, 12, 00, 00);
Appointment appointment3 = new Appointment();
appointment3.StartDate = new DateTime(2018, 07, 11, 09, 00, 00);
appointment3.FinishDate = new DateTime(2018, 07, 11, 12, 00, 00);
Appointment appointment4 = new Appointment();
appointment4.StartDate = new DateTime(2018, 07, 11, 14, 00, 00);
appointment4.FinishDate = new DateTime(2018, 07, 11, 16, 00, 00);
Appointment appointment5 = new Appointment();
appointment5.StartDate = new DateTime(2018, 07, 11, 15, 00, 00);
appointment5.FinishDate = new DateTime(2018, 07, 11, 17, 00, 00);
Appointment appointment6 = new Appointment();
appointment6.StartDate = new DateTime(2018, 07, 11, 18, 00, 00);
appointment6.FinishDate = new DateTime(2018, 07, 11, 19, 00, 00);
appointments.Add(appointment1);
appointments.Add(appointment2);
appointments.Add(appointment3);
appointments.Add(appointment4);
appointments.Add(appointment5);
appointments.Add(appointment6);
var ranges = appointments.Select(a => new Range {Start=a.StartDate, End=a.FinishDate});
var total = MergeTimes(ranges).Sum(a => (a.End-a.Start).TotalHours);
Console.WriteLine(total);
}
public class Appointment
{
public DateTime StartDate { get; set; }
public DateTime FinishDate { get; set; }
}
public class Range
{
public DateTime Start {get;set;}
public DateTime End {get;set;}
}
public IEnumerable<Range> MergeTimes(IEnumerable<Range> times)
{
if (times.Count() == 0)
{
return times;
}
Range[] orderedTimes = (from t in times
orderby t.Start
select t).ToArray();
List<Range> merged = new List<Range>();
Range current = new Range
{
Start = orderedTimes[0].Start,
End = orderedTimes[0].End
};
for (int i = 0; i < orderedTimes.Length; i++)
{
if (current.Start <= orderedTimes[i].End && current.End >= orderedTimes[i].Start)
{
current.Start = ((current.Start < orderedTimes[i].Start) ? current.Start : orderedTimes[i].Start);
current.End = ((current.End > orderedTimes[i].End) ? current.End : orderedTimes[i].End);
}
else
{
merged.Add(new Range
{
Start = current.Start,
End = current.End
});
current = new Range
{
Start = orderedTimes[i].Start,
End = orderedTimes[i].End
};
}
}
merged.Add(new Range
{
Start = current.Start,
End = current.End
});
return merged;
}
Let's sort the appointments and then Aggregate them: we have only 3 choices to implement:
Appointments disjoint
Appointment includes the next appointment
Appointments overlap
Sample code:
var total = appointments
.OrderBy(appointment => appointment.StartDate)
.Aggregate(new Tuple<double, DateTime?>(0.0, null), (acc, item) => {
if (!acc.Item2.HasValue || acc.Item2.Value <= item.StartDate) // Disjoint
return new Tuple<double, DateTime?>(
acc.Item1 + (item.FinishDate - item.StartDate).TotalHours,
item.FinishDate);
else if (acc.Item2.Value >= item.FinishDate) // Include
return acc;
else // Partially overlap
return new Tuple<double, DateTime?>(
acc.Item1 + (item.FinishDate - acc.Item2.Value).TotalHours,
item.FinishDate);
})
.Item1;
// 8
Console.WriteLine(total);
Are you aware of the properties on the TimeSpan class?
(dateA - dateB).TotalMinutes
https://msdn.microsoft.com/en-us/library/system.timespan.totalminutes.aspx
One way to solve this would be to gather the hours that are covered by appointments, then group them.
You could add a method to the Appointment class to get the hours covered by the appointment:
public IEnumerable<int> GetHours()
{
List<int> hours = new List<int>();
var startDate = StartDate;
var finishDate = FinishDate;
while(startDate < finishDate)
{
hours.Add(startDate.Hour);
startDate = startDate.AddHours(1);
}
return hours;
}
You can then group them:
var result = appointments.SelectMany(a => a.GetHours()).GroupBy(i => i);
Console.WriteLine("Total hours: {0}", result.Count()); //This is the count
foreach (var hour in result)
{
Console.WriteLine("{0} => {1}", hour.Key, hour.Count());
}
Output in console:
Total hours: 8
8 => 1
9 => 2
10 => 3
11 => 2
14 => 1
15 => 2
16 => 1
18 => 1
I was hoping for some help with something I have been working on.
I have an ASP.NET web form that is trying to be a calculator, now I have dates and days of the week sorted as well as other forms of other parts working.
Now I need to add public holidays to this form.
I have an array holding the dates and if I put a date range of any type I get the full count as if it was counting for a full year.
And the intent is to read the date rage and pick the holidays in said date rage and only show said dates e.g.over two years the count should be double.
I'm sure it's something simple, I'm just not seeing it.
public class Program
{
public static void Main()
{
DisplayDayInfo(new DateTime(2018, 01, 01), new DateTime(2019, 01, 01));
// Show info for April 2018
//DisplayDayInfo(new DateTime(2018, 04, 01), new DateTime(2018, 05, 01));
}
private static int GetDayCount(IEnumerable<DateTime>dates, DayOfWeek dayOfWeek)
{
return dates == null ? 0 : dates.Count(date => date.DayOfWeek == dayOfWeek);
}
private static int GetHoliDayCount(IEnumerable<DateTime> holiday, DayOfWeek dayOfWeek)
{
DateTime[] holidayState = new DateTime[]
{
new DateTime(DateTime.Now.Year, 1, 1),
new DateTime(DateTime.Now.Year, 1, 26),
new DateTime(DateTime.Now.Year, 3, 30),
new DateTime(DateTime.Now.Year, 3, 31),
new DateTime(DateTime.Now.Year, 4, 1),
new DateTime(DateTime.Now.Year, 4, 2),
new DateTime(DateTime.Now.Year, 4, 25),
new DateTime(DateTime.Now.Year, 5, 7),
new DateTime(DateTime.Now.Year, 8, 15),
new DateTime(DateTime.Now.Year, 9, 1),
new DateTime(DateTime.Now.Year, 12, 25),
new DateTime(DateTime.Now.Year, 12, 26)
};
return holiday == null ? 0 : holidayState.Count(date => date.DayOfWeek == dayOfWeek);
}
private static void DisplayDayInfo(DateTime fromDate, DateTime toDate)
{
var numDays = toDate.Subtract(fromDate).Days;
Console.WriteLine("Total number of days from {0} to {1}: {2}\n",fromDate.ToShortDateString(), toDate.ToShortDateString(), numDays);
var dates = Enumerable.Range(0, numDays).Select(days => fromDate.AddDays(days)).ToArray();
var holiday = Enumerable.Range(0, numDays).Select(days => fromDate.AddDays(days)).ToArray();
foreach (DayOfWeek dayOfWeek in Enum.GetValues(typeof(DayOfWeek)))
{
Console.WriteLine("{0} {1} ", dayOfWeek, GetDayCount(dates, dayOfWeek));
}
Console.WriteLine("****************************************************");
foreach (DayOfWeek dayOfWeek in Enum.GetValues(typeof(DayOfWeek)))
{
Console.WriteLine("{0} {1} ", dayOfWeek, GetHoliDayCount(holiday, dayOfWeek));
}
}
}
https://dotnetfiddle.net/XjoCpf
Any help would be grate, Thank you.
I changed some implementation of your methods based on your intent:
private static DateTime? GetHoliDayCount(DateTime holiday)
{
DateTime? holidayToReturn = null ;
DateTime[] holidayState = new DateTime[]
{
new DateTime(DateTime.Now.Year, 1, 1),
new DateTime(DateTime.Now.Year, 1, 26),
new DateTime(DateTime.Now.Year, 3, 30),
new DateTime(DateTime.Now.Year, 3, 31),
new DateTime(DateTime.Now.Year, 4, 1),
new DateTime(DateTime.Now.Year, 4, 2),
new DateTime(DateTime.Now.Year, 4, 25),
new DateTime(DateTime.Now.Year, 5, 7),
new DateTime(DateTime.Now.Year, 8, 15),
new DateTime(DateTime.Now.Year, 9, 1),
new DateTime(DateTime.Now.Year, 12, 25),
new DateTime(DateTime.Now.Year, 12, 26)
};
if (holidayState.Contains(holiday))
{
holidayToReturn = holiday;
}
return holidayToReturn;
}
Then you need to modify your DisplayDateInfo to loop over the holiday enumerable.
private static void DisplayDayInfo(DateTime fromDate, DateTime toDate)
{
var numDays = toDate.Subtract(fromDate).Days;
Console.WriteLine("Total number of days from {0} to {1}: {2}\n", fromDate.ToShortDateString(), toDate.ToShortDateString(), numDays);
var dates = Enumerable.Range(0, numDays).Select(days => fromDate.AddDays(days)).ToArray();
var holiday = Enumerable.Range(0, numDays).Select(days => fromDate.AddDays(days)).ToArray();
foreach (DayOfWeek dayOfWeek in Enum.GetValues(typeof(DayOfWeek)))
{
Console.WriteLine("{0} {1} ", dayOfWeek, GetDayCount(dates, dayOfWeek));
}
Console.WriteLine("****************************************************");
foreach (DateTime dayOfWeek in holiday)
{
string holidayToWrite = GetHoliDayCount(dayOfWeek).ToString();
if (holidayToWrite != "")
Console.WriteLine("{0} ", holidayToWrite);
}
}
Result:
Or if you don't want to edit the method signature of your GetHolidayCount method and do no changes in your DisplayDateInfo method, you can do this by comparing your IEnumerable range to the dates in the array, and if an item in the array contains the date in your IEnumerable then add it to the final list.:
private static int GetHoliDayCount(IEnumerable<DateTime> holiday, DayOfWeek dayOfWeek)
{
List<DateTime> days = holiday.ToList(); //convert this to list
List<DateTime> daysToAdd = new List<DateTime>(); //have a list as container for the holidays after the comparison.
DateTime[] holidayState = new DateTime[]
{
new DateTime(DateTime.Now.Year, 1, 1),
new DateTime(DateTime.Now.Year, 1, 26),
new DateTime(DateTime.Now.Year, 3, 30),
new DateTime(DateTime.Now.Year, 3, 31),
new DateTime(DateTime.Now.Year, 4, 1),
new DateTime(DateTime.Now.Year, 4, 2),
new DateTime(DateTime.Now.Year, 4, 25),
new DateTime(DateTime.Now.Year, 5, 7),
new DateTime(DateTime.Now.Year, 8, 15),
new DateTime(DateTime.Now.Year, 9, 1),
new DateTime(DateTime.Now.Year, 12, 25),
new DateTime(DateTime.Now.Year, 12, 26)
};
foreach (DateTime day in days)
{
if (holidayState.Contains(day))
{
daysToAdd.Add(day);
}
}
holiday = daysToAdd;
return holiday == null ? 0 : holidayState.Count(date => date.DayOfWeek == dayOfWeek);
}
You can also use this method if you don't want the instantiation of your holidayState array to be limited to the current year. What this does is that it groups the years in your enumerable and runs the comparison of your holiday enumerable to the array for each year in the grouping:
private static int GetHoliDayCount(IEnumerable<DateTime> holiday, DayOfWeek dayOfWeek)
{
var yearsGroup = holiday.GroupBy(x => x.Year);
List<DateTime> daysToAdd = new List<DateTime>();
DateTime[] holidayState = null;
foreach (var year in yearsGroup)
{
List<DateTime> days = holiday.Where(x => x.Year == Convert.ToInt32(year.Key)).ToList();
holidayState = new DateTime[]
{
new DateTime(Convert.ToInt32(year.Key), 1, 1),
new DateTime(Convert.ToInt32(year.Key), 1, 26),
new DateTime(Convert.ToInt32(year.Key), 3, 30),
new DateTime(Convert.ToInt32(year.Key), 3, 31),
new DateTime(Convert.ToInt32(year.Key), 4, 1),
new DateTime(Convert.ToInt32(year.Key), 4, 2),
new DateTime(Convert.ToInt32(year.Key), 4, 25),
new DateTime(Convert.ToInt32(year.Key), 5, 7),
new DateTime(Convert.ToInt32(year.Key), 8, 15),
new DateTime(Convert.ToInt32(year.Key), 9, 1),
new DateTime(Convert.ToInt32(year.Key), 12, 25),
new DateTime(Convert.ToInt32(year.Key), 12, 26)
};
foreach (DateTime day in days)
{
if (holidayState.Contains(day))
{
daysToAdd.Add(day);
}
}
}
holiday = daysToAdd;
return holiday == null ? 0 : holidayState.Count(date => date.DayOfWeek == dayOfWeek);
}
UPDATE: Using my first implementation stated above, I was able to get all dates for a given range (say 6 months). I don't know if this is what you need.
I would like to know the best way to set a range of dates. I have logic that checks what day a certain record is approved on and based on that day i set a date the next time that record needs to be re-approved
so if the record is approved in january or february it should be re evaluated in march if its approved in march it should be re evaluated in june.
i declare my ranges like this for now, but this i believe is not the best way to do it
DateTime quarterOneStart = new DateTime(DateTime.Now.Year,07,01);
DateTime quarterOneEnd = new DateTime(DateTime.Now.Year, 09, 15));
DateTime quarterTwoStart = new DateTime(DateTime.Now.Year, 10, 01);
DateTime quarterTwoEnd = new DateTime(DateTime.Now.Year, 12, 15));
DateTime quarterThreeStart = new DateTime(DateTime.Now.Year, 01, 01);
DateTime quarterThreeEnd = new DateTime(DateTime.Now.Year, 03, 15));
DateTime quarterFourStart = new DateTime(DateTime.Now.Year, 04, 01);
DateTime quarterFourEnd = new DateTime(DateTime.Now.Year, 06, 15));
is there a better way to set the date time variables above?
What about class for quarter
public class Quarter {
private readonly DateTime _startDate;
private readonly DateTime _endDate;
public Quarter(DateTime startDate, DateTime endDate) {
_startDate = startDate;
_endDate = endDate;
}
public DateTime StartDate => _startDate;
public DateTime EndDate => _endDate;
}
and use it
Quarter one = new Quarter(new DateTime(2017, 07, 01), new DateTime(2017, 09, 15));
Quarter two = new Quarter(new DateTime(2017, 09, 15), new DateTime(2017, 10, 01));
...
Rather than creating multiple variables, you can create a Dictionary of items key'ed by an enum. For example:
public enum Quaters
{
Q1_Start,
Q1_End,
Q2_Start,
Q2_End,
Q3_Start,
Q3_End,
Q4_Start,
Q4_End
}
Dictionary<Quaters, DateTime> dateRange = new Dictionary<Quaters, DateTime>
{
{Quaters.Q1_Start, new DateTime(DateTime.Now.Year, 07, 01)},
{Quaters.Q1_End, new DateTime(DateTime.Now.Year, 09, 15)},
{Quaters.Q2_Start, new DateTime(DateTime.Now.Year, 10, 01)},
{Quaters.Q2_End, new DateTime(DateTime.Now.Year, 12, 15)},
...
};
When you need to verify the value against any range parameter you can index the dateRange dictionary based on keys. It is just a proposal and there could be better solutions to your actual problem.
In the past I've written a FinancialYear class that internally holds a startYear (int) variable and offers various methods/properties, e.g. (among others)
public DateTime StartDate
{
get { return new DateTime(_startYear, 4, 1); } // April 1st
}
public static FinancialYear ForDate(DateTime dt)
{
DateTime finYearStart = new DateTime(dt.Year, 4, 1);
return (dt >= finYearStart) ? new FinancialYear(dt.Year) : new FinancialYear(dt.Year - 1);
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
private void GetTimeBetween()
{
DateTime a = new DateTime(2010, 04, 24, 13, 10, 00);
DateTime b = new DateTime(2010, 04, 25, 13, 10, 00);
Console.WriteLine(b.Subtract(a).TotalMinutes);
double d = b.Subtract(a).TotalMinutes;
}
I'm getting TotalMinutes 1440
But how can i make now that it will create a List with all the dates and time between this two dates between a and b but in jumps of 10 minutes ?
For example in the List the first item will be:
24/4/2010 13:10:00
Then ext item will be
24/4/2010 13:20:00
And so on until b
25/4/2010 13:10:00
In this format in the List or in other formats but the idea to get all the dates+time between the two given dates.
Gee, sometimes its fun to overengineer things. There is an Aggregate function which turns a list into a scalar value - lets create one that goes the other way
public static class Extensions
{
public static IEnumerable<T> Explode<T>(this T value, Func<T,T> next, Func<T,bool> limit)
{
var n = value;
while(!limit(n))
{
yield return n;
n = next(n);
}
}
}
Usage:
DateTime a = new DateTime(2010, 04, 24, 13, 10, 00);
DateTime b = new DateTime(2010, 04, 25, 13, 10, 00);
var result = a.Explode(x => x.AddMinutes(10), x => x>b).ToList();
Live example: http://rextester.com/WCGZL87983
You could loop it:
var list = new List<DateTime>();
var start = new DateTime(2010, 04, 24, 13, 10, 00);
var end = new DateTime(2010, 04, 25, 13, 10, 00);
for (DateTime date = start; date <= end; date = date.AddMinutes(10))
list.Add(date);
Try this
var start = new DateTime(2010, 04, 24, 13, 10, 00);
var end = new DateTime(2010, 04, 25, 13, 10, 00);
for (DateTime date = start; date <= end; date = date.AddMinutes(10))
{
Console.WriteLine(date.ToString("dd/mm/yyyy HH:mm:ss"));
}