I am trying to iterate between 2 dates received as inputs and print every 5 minutes (during working hours)
Seems like I am getting to an endless and can get my app stop at endTime
DateTime startDate = new DateTime(2018, 1, 1);
DateTime endDate = new DateTime(2018, 3, 1);
// day in month
for (DateTime date = startDate; date < endDate; date = date.AddDays(1))
{
if (date.DayOfWeek == DayOfWeek.Friday || date.DayOfWeek == DayOfWeek.Saturday)
continue;
//iterate every hour
for (var hour = date; hour < hour.AddDays(1); hour = hour.AddHours(1))
{
if (hour.Hour < 8 || hour.Hour > 17)
continue;
//iterate every minute
for (var min = date; min <= min.AddDays(1); min = min.AddMinutes(5))
{
Console.WriteLine(min);
}
}
}
Maybe you're overcomplicating; take a look into this:
var startDate = new DateTime(2018, 1, 1);
var endDate = new DateTime(2018, 3, 1);
while ((startDate = startDate.AddMinutes(5)) < endDate)
{
if (startDate.Hour < 8 || startDate.Hour > 17 ||
startDate.DayOfWeek == DayOfWeek.Saturday ||
startDate.DayOfWeek == DayOfWeek.Sunday)
continue;
Console.WriteLine("{0:ddd, MMM dd, yyyy HH:mm}", startDate);
}
You just need a loop, incrementing by 5 minutes until the endDate is met; inside the loop you skip all values you don't want (weekends and non-business hours).
In this code I'm reusing the startDate as work variable, but you definitely could create a new one and make things clearer.
Related
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
Hi everybody i'm working a project about calculate specific working days.
My conditions are : Saturday is not holiday, it is working day.
I wrote this code everyting is okey skipped Sundays only , but i want to skip if contains a holiday date.
Problem : skipping Sunday but not skipping passing holiday list values.
Future Date Calculate function :
public DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays,
List<DateTime> holidays)
{
var futureDate = fromDate;
for (var i = 0; i < numberofWorkDays; i++)
{
if (
futureDate.DayOfWeek == DayOfWeek.Sunday
|| (holidays != null && holidays.Contains(futureDate)))
{
futureDate = futureDate.AddDays(1);
numberofWorkDays++;
}
else
{
futureDate = futureDate.AddDays(1);
}
}
while (
futureDate.DayOfWeek == DayOfWeek.Sunday
|| (holidays != null && holidays.Contains(futureDate)))
{
futureDate = futureDate.AddDays(1);
}
return futureDate;
}
Main function:
List<DateTime> holidayslist = new List<DateTime>();
holidayslist.Add(new DateTime(2016, 09, 7));
holidayslist.Add(new DateTime(2016, 09, 8));
holidayslist.Add(new DateTime(2016, 09, 9));
DateTime izinbaslangic = Convert.ToDateTime(dtpÄ°zinBaslangicTarihi.Value, System.Globalization.CultureInfo.CreateSpecificCulture("tr-TR").DateTimeFormat);
dtpÄ°zinBitisTarihi.Value = CalculateFutureDate(izinbaslangic, Int32.Parse(tbÄ°zinGunu.Text), holidayslist);
Inputs : izinbaslangic -> datetimepicker value and workingdays -> tbizingunu value
Expecting Outputs : exclude holiday and weekends show in another datetimepicker new date.
Output : Only skipping Weekends.Not skipping holidays.
Expecting Output Image : enter image description here
I would rewrite your code in the following way
public DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays,
List<DateTime> holidays)
{
var futureDate = fromDate;
while (numberofWorkDays != 0)
{
if (!isHoliday(futureDate, holidays))
numberofWorkDays--;
futureDate = futureDate.AddDays(1);
}
while (isHoliday(futureDate, holidays))
futureDate = futureDate.AddDays(1);
return futureDate;
}
bool isHoliday(DateTime testDate, List<DateTime>holidays)
{
return (testDate.DayOfWeek == DayOfWeek.Sunday
|| (holidays != null && holidays.Contains(testDate.Date)));
}
The idea is simply to create a loop until the number of working days required is reduced to zero. Also isolating the logic to test for an holiday will help a lot in a better understanding of the code and avoid a dangerous duplication of the same logic
List<DateTime> holidayslist = new List<DateTime>();
holidayslist.Add(new DateTime(2016, 09, 7));
holidayslist.Add(new DateTime(2016, 09, 8));
holidayslist.Add(new DateTime(2016, 09, 9));
DateTime start = new DateTime(2016,9,7);
DateTime ending = CalculateFutureDate(start, 1, holidayslist);
Console.WriteLine(ending.ToString()); // 12/09/2016 00:00:00
I have list of events, each event has two dates; start date and end date. I want to create a filter by months. How do I return dates that ranges between a month that a user selects?
for example, lets say the user selects month October, I want to return all events that are within this month.
I have used this to get the dates that ranges between todays date but now stuck on how to get the range between a month.
DateTime dateToCheck = DateTime.Today.Date;
DateTime startDate = DateTime.Parse(item["Start Time"].ToString());
DateTime endDate = DateTime.Parse(item["End Time"].ToString());
foreach (SPListItem item in collection)
{
if (startDate <= dateToCheck && dateToCheck < endDate)
{
ListBox1.Items.Add(item["EventTitle"].ToString());
}
}
// set up dummy data
var dates = new[] {DateTime.Now, DateTime.Now, DateTime.Now};
int month = GetMonth();
// get result
var result = dates.Where(date => date.Month == month);
EDIT: if you need to make sure the dates have the correct year as well, use
var dates = new[] {DateTime.Now, DateTime.Now, DateTime.Now};
int year = GetYear();
int month = GetMonth();
var result = dates.Where(date => date.Year == year && date.Month == month);
Of course, you can get the year/month numbers as well as the date-list from wherever.
EDIT2: if you get a DateTime object as input modify accordingly:
var dates = new[] {DateTime.Now, DateTime.Now, DateTime.Now};
var input = GetDateTime();
var result = dates.Where(date => date.Year == input.Year && date.Month == input.Month);
You still can use your code with little modifications. As start date you have to select 00:00 time of 1st of the month and as end date you have to use 00:00 time of 1st of the next month. In case of October 2015 it would be: 1 Oct 2015 <= date < 1 Nov 2015.
int year = 2015;
int month = 10;
DateTime dateToCheck = DateTime.Today.Date;
DateTime startDate = new DateTime(year, month, 1);
DateTime endDate = startDate.AddMonths(1);
foreach (SPListItem item in collection)
{
if (startDate <= dateToCheck && dateToCheck < endDate)
{
ListBox1.Items.Add(item["EventTitle"].ToString());
}
}
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.
I am stuck for sometime now, now need your help.
I want to display in a dropdown only fourth Sunday of each month, say from 1-Sep-2010 to 31-Aug-2011
I only want fourth Sunday in dropdown list, how to do it using asp.net C#
Regards
Here is an approach that uses a little LINQ and the knowledge that the fourth Sunday will occur between the 22nd and 28th of a month, inclusive.
DateTime startDate = new DateTime(2010, 9, 1);
DateTime endDate = startDate.AddYears(1).AddDays(-1);
List<DateTime> fourthSundays = new List<DateTime>();
DateTime currentDate = startDate;
while (currentDate < endDate)
{
// we know the fourth sunday will be the 22-28
DateTime fourthSunday = Enumerable.Range(22, 7).Select(day => new DateTime(currentDate.Year, currentDate.Month, day)).Single(date => date.DayOfWeek == DayOfWeek.Sunday);
fourthSundays.Add(fourthSunday);
currentDate = currentDate.AddMonths(1);
}
You can then bind that List<DateTime> to the dropdown or skip the list itself in favor of adding the items as you generate them to the dropdown, like below.
yourDropdown.Items.Add(new ListItem(fourthSunday.ToString()));
For giggles, you can do the whole thing in a LINQ statement and skip (most of) the variables.
DateTime startDate = new DateTime(2010, 9, 1);
IEnumerable<DateTime> fourthSundays =
Enumerable.Range(0, 12)
.Select(item => startDate.AddMonths(item))
.Select(currentMonth =>
Enumerable.Range(22, 7)
.Select(day => new DateTime(currentMonth.Year, currentMonth.Month, day))
.Single(date => date.DayOfWeek == DayOfWeek.Sunday)
);
Got bored so here you go. Two helper methods one retrieves the Week if it exist, and the other iterates through the months
class Program
{
static void Main(string[] args)
{
DateTime startDate = new DateTime(2010, 09, 1);
foreach(DateTime dt in EachMonth( new DateTime(2010, 09, 1), new DateTime(2011, 09, 1))){
DateTime? result = GetDayByWeekOffset(DayOfWeek.Sunday, dt, 4);
Console.WriteLine("Sunday:" + (result.HasValue?result.Value.ToString("MM-dd-yyyy"):"null"));
}
Console.ReadKey();
}
public static DateTime? GetDayByWeekOffset(DayOfWeek day, DateTime month, int weekOffSet)
{
//First day of month
DateTime firstDayOfMonth = month.AddDays((-1 * month.Day) + 1);
//
int daysOffSet;
daysOffSet= ((int)day + 7 - (int)firstDayOfMonth.DayOfWeek) % 7;
DateTime firstDay = month.AddDays(daysOffSet);
// Add the number of weeks specified
DateTime resultDate = firstDay.AddDays((weekOffSet - 1) * 7);
if (resultDate.Month != firstDayOfMonth.Month){
return null;
}else{
return resultDate;
}
}
public static IEnumerable<DateTime> EachMonth(DateTime from, DateTime thru)
{
for (var month = from.Date; month.Date <= thru.Date; month = month.AddMonths(1))
yield return month;
}
}
Anthony's answer above is nice, I like it a lot. As an alternate, here is a method which is parameterized for the day of the week and the week number (i.e. if you need other combinations, like 4th Sunday, 3rd Friday, etc.) with some comments.
Call it like this for your case:
List<DateTime> sundays = DateInstances(new DateTime(2010, 9, 1), new DateTime(2011, 8, 31), DayOfWeek.Sunday, 4);
And the method itself:
public List<DateTime> DateInstances(DateTime start, DateTime end, DayOfWeek day, int weeks)
{
if (start > end)
throw new ArgumentOutOfRangeException("end", "The start date must occur before the end date");
List<DateTime> results = new List<DateTime>();
DateTime temp = start;
while (temp < end)
{
DateTime firstWeekday = new DateTime(temp.Year, temp.Month, 1);
//increment to the given day (i.e. if we want the 4th sunday, we must find the first sunday of the month)
while (firstWeekday.DayOfWeek != day)
firstWeekday = firstWeekday.AddDays(1);
//add the number of weeks (note: we already have the first instance, so subtract 1)
firstWeekday = firstWeekday.AddDays(7 * (weeks - 1));
//make sure we haven't gone over to the next month
if (firstWeekday.Month == temp.Month)
results.Add(firstWeekday);
//let's not loop forever ;)
temp = temp.AddMonths(1);
}
return results;
}