The number of days in a date range, excluding weekends and other dates, in C #

I have a C # method as follows:

public static int DaysLeft(DateTime startDate, DateTime endDate, Boolean excludeWeekends, String excludeDates) { } 

What he should do is calculate the number of days between startDate and endDate, but you don't need to exclude weekends and other dates (passed as a string of dates separated by commas).

I do not know how to solve this. My gut instinct would have to loop from startDate to endDate and do some string comparisons, but from what I can find out, C # doesn't allow dates to be quoted in this way - or at least it's not a very elegant way to do that- that.

+7
source share
7 answers

Here is one example that includes excluded dates, weekends, and a loop. However, I changed the line excludeDates to List. Need to add some null check.

  public static int DaysLeft(DateTime startDate, DateTime endDate, Boolean excludeWeekends, List<DateTime> excludeDates) { int count = 0; for (DateTime index = startDate; index < endDate; index = index.AddDays(1)) { if (excludeWeekends && index.DayOfWeek != DayOfWeek.Sunday && index.DayOfWeek != DayOfWeek.Saturday) { bool excluded = false; ; for (int i = 0; i < excludeDates.Count; i++) { if (index.Date.CompareTo(excludeDates[i].Date) == 0) { excluded = true; break; } } if (!excluded) { count++; } } } return count; } 

EDIT: I want to point out that I find this a quick and dirty method - unless you have to do this often. If you are doing this a lot and the distance between startDate and endDate is quite large, it would be much better to do the math, as indicated in one of the other answers. This is suggested in order to get an idea of ​​repeat dates.

+8
source

Oh, it's very easy to iterate over dates - this is not a problem at all:

 // I'm assuming you want <= to give an *inclusive* end date... for (DateTime date = start; date <= end; date = date.AddDays(1)) { // Do stuff with date } 

You can also easily write IEnumerable<DateTime> and use foreach .

I would try to avoid doing string operations here if possible, although, in fact, these dates are not strings, so if you can work in the problem area as much as possible, this will simplify the work.

Of course, there may be more effective ways than a cycle, but it will be more difficult for them to succeed. If the loop is ok in terms of performance, I will stick with this.

As a quick plugin for my own open source project, Noda Time has a more diverse set of types representing dates and times - in which case you will use LocalDate . Thus, you do not need to worry about what happens if the time at the “start” is later than the time at the “end”, etc. On the other hand, Noda Time is not over yet ... the bits you need for this are ready and should work fine, but it is possible that the API may still change in the future.

EDIT: If you often need to quote dates, you might need something like this extension method (put it in a nonequivalent static top-level class):

 public static IEnumerable<DateTime> To(this DateTime start, DateTime end) { Date endDate = end.Date; for (DateTime date = start.Date; date <= endDate; date = date.AddDays(1)) { yield return date; } } 

Then:

 foreach (DateTime date in start.To(end)) { ... } 
+10
source

The supersonic sugar library has many helpers for handling DateTime manipulations.

You can find the full list on the Subsonic site , and the source code is on github .

+1
source

Here's the pseudo code for another approach that I used in SQL:

Find the total number of days between two dates
Subtract the number of days off
Delete the day if the start date is Sunday Delete the day if the start date is Saturday
Remove any other days that you don't need (see my comment above how to do this in C #)

0
source

This may work and avoid a solution like O (n):

 public int DaysLeft(DateTime startDate, DateTime endDate, Boolean excludeWeekends, String excludeDates) { //Work out days in range int days = (int)endDate.Subtract(startDate).TotalDays + 1; if (excludeWeekends) { //Remove most weekends by removing 2 in 7 days (rounded down) days -= ((int)Math.Floor((decimal)(days / 7)) * 2); if (startDate.DayOfWeek == DayOfWeek.Sunday) days -= 1; if (startDate.DayOfWeek == DayOfWeek.Saturday) days -= 2; } return days; } 

It is not exhaustively verified.

To handle the dates of exceptions, you can iterate over them and exclude where they are between the beginning and the end (and not the weekend, if necessary). It should be a shorter cycle than after all days between the beginning and the end.

0
source

Combine with LINQ expressions,

  public int GetNoOfLeaveDays(DateTime fromDate, DateTime toDate, Boolean excludeWeekends, List<DateTime> excludeDates) { var count = 0; for (DateTime index = fromDate; index <= toDate; index = index.AddDays(1)) { if (!excludeWeekends || index.DayOfWeek == DayOfWeek.Saturday || index.DayOfWeek == DayOfWeek.Sunday) continue; var excluded = excludeDates.Any(t => index.Date.CompareTo(t.Date) == 0); if (!excluded) count++; } return count; } 
0
source
 private int workingdays(int month,int year) { int daysInMonth = 0; int days = DateTime.DaysInMonth(year, month); for (int i = 1; i <= days; i++) { DateTime day = new DateTime(year, month, i); if (day.DayOfWeek != DayOfWeek.Sunday && day.DayOfWeek != DayOfWeek.Saturday) { daysInMonth++; } } return daysInMonth; } 
0
source

All Articles