Addbusinessdays and Getbusinessdays

AddBusinessDays and GetBusinessDays

Latest attempt for your first function:

public static DateTime AddBusinessDays(DateTime date, int days)
{
if (days < 0)
{
throw new ArgumentException("days cannot be negative", "days");
}

if (days == 0) return date;

if (date.DayOfWeek == DayOfWeek.Saturday)
{
date = date.AddDays(2);
days -= 1;
}
else if (date.DayOfWeek == DayOfWeek.Sunday)
{
date = date.AddDays(1);
days -= 1;
}

date = date.AddDays(days / 5 * 7);
int extraDays = days % 5;

if ((int)date.DayOfWeek + extraDays > 5)
{
extraDays += 2;
}

return date.AddDays(extraDays);

}

The second function, GetBusinessDays, can be implemented as follows:

public static int GetBusinessDays(DateTime start, DateTime end)
{
if (start.DayOfWeek == DayOfWeek.Saturday)
{
start = start.AddDays(2);
}
else if (start.DayOfWeek == DayOfWeek.Sunday)
{
start = start.AddDays(1);
}

if (end.DayOfWeek == DayOfWeek.Saturday)
{
end = end.AddDays(-1);
}
else if (end.DayOfWeek == DayOfWeek.Sunday)
{
end = end.AddDays(-2);
}

int diff = (int)end.Subtract(start).TotalDays;

int result = diff / 7 * 5 + diff % 7;

if (end.DayOfWeek < start.DayOfWeek)
{
return result - 2;
}
else{
return result;
}
}

Adding Days to a Date but Excluding Weekends

using Fluent DateTime https://github.com/FluentDateTime/FluentDateTime

var dateTime = DateTime.Now.AddBusinessDays(4);

Calculate the number of business days between two dates?

I've had such a task before and I've got the solution.
I would avoid enumerating all days in between when it's avoidable, which is the case here. I don't even mention creating a bunch of DateTime instances, as I saw in one of the answers above. This is really waste of processing power. Especially in the real world situation, when you have to examine time intervals of several months.
See my code, with comments, below.

    /// <summary>
/// Calculates number of business days, taking into account:
/// - weekends (Saturdays and Sundays)
/// - bank holidays in the middle of the week
/// </summary>
/// <param name="firstDay">First day in the time interval</param>
/// <param name="lastDay">Last day in the time interval</param>
/// <param name="bankHolidays">List of bank holidays excluding weekends</param>
/// <returns>Number of business days during the 'span'</returns>
public static int BusinessDaysUntil(this DateTime firstDay, DateTime lastDay, params DateTime[] bankHolidays)
{
firstDay = firstDay.Date;
lastDay = lastDay.Date;
if (firstDay > lastDay)
throw new ArgumentException("Incorrect last day " + lastDay);

TimeSpan span = lastDay - firstDay;
int businessDays = span.Days + 1;
int fullWeekCount = businessDays / 7;
// find out if there are weekends during the time exceedng the full weeks
if (businessDays > fullWeekCount*7)
{
// we are here to find out if there is a 1-day or 2-days weekend
// in the time interval remaining after subtracting the complete weeks
int firstDayOfWeek = (int) firstDay.DayOfWeek;
int lastDayOfWeek = (int) lastDay.DayOfWeek;
if (lastDayOfWeek < firstDayOfWeek)
lastDayOfWeek += 7;
if (firstDayOfWeek <= 6)
{
if (lastDayOfWeek >= 7)// Both Saturday and Sunday are in the remaining time interval
businessDays -= 2;
else if (lastDayOfWeek >= 6)// Only Saturday is in the remaining time interval
businessDays -= 1;
}
else if (firstDayOfWeek <= 7 && lastDayOfWeek >= 7)// Only Sunday is in the remaining time interval
businessDays -= 1;
}

// subtract the weekends during the full weeks in the interval
businessDays -= fullWeekCount + fullWeekCount;

// subtract the number of bank holidays during the time interval
foreach (DateTime bankHoliday in bankHolidays)
{
DateTime bh = bankHoliday.Date;
if (firstDay <= bh && bh <= lastDay)
--businessDays;
}

return businessDays;
}

Edit by Slauma, August 2011

Great answer! There is little bug though. I take the freedom to edit this answer since the answerer is absent since 2009.

The code above assumes that DayOfWeek.Sunday has the value 7 which is not the case. The value is actually 0. It leads to a wrong calculation if for example firstDay and lastDay are both the same Sunday. The method returns 1 in this case but it should be 0.

Easiest fix for this bug: Replace in the code above the lines where firstDayOfWeek and lastDayOfWeek are declared by the following:

int firstDayOfWeek = firstDay.DayOfWeek == DayOfWeek.Sunday 
? 7 : (int)firstDay.DayOfWeek;
int lastDayOfWeek = lastDay.DayOfWeek == DayOfWeek.Sunday
? 7 : (int)lastDay.DayOfWeek;

Now the result is:

  • Friday to Friday -> 1
  • Saturday to Saturday -> 0
  • Sunday to Sunday -> 0
  • Friday to Saturday -> 1
  • Friday to Sunday -> 1
  • Friday to Monday -> 2
  • Saturday to Monday -> 1
  • Sunday to Monday -> 1
  • Monday to Monday -> 1

How to Subtract Business days?

See this Answer

(Linked answer has been duplicated below for convenience)

using Fluent DateTime:

var now = DateTime.Now;
var dateTime1 = now.AddBusinessDays(3);
var dateTime2 = now.SubtractBusinessDays(5);

internal code is as follows

/// <summary>
/// Adds the given number of business days to the <see cref="DateTime"/>.
/// </summary>
/// <param name="current">The date to be changed.</param>
/// <param name="days">Number of business days to be added.</param>
/// <returns>A <see cref="DateTime"/> increased by a given number of business days.</returns>
public static DateTime AddBusinessDays(this DateTime current, int days)
{
var sign = Math.Sign(days);
var unsignedDays = Math.Abs(days);
for (var i = 0; i < unsignedDays; i++)
{
do
{
current = current.AddDays(sign);
}
while (current.DayOfWeek == DayOfWeek.Saturday ||
current.DayOfWeek == DayOfWeek.Sunday);
}
return current;
}

/// <summary>
/// Subtracts the given number of business days to the <see cref="DateTime"/>.
/// </summary>
/// <param name="current">The date to be changed.</param>
/// <param name="days">Number of business days to be subtracted.</param>
/// <returns>A <see cref="DateTime"/> increased by a given number of business days.</returns>
public static DateTime SubtractBusinessDays(this DateTime current, int days)
{
return AddBusinessDays(current, -days);
}

Date calculation in c#

You could use LINQ:

DayOfWeek[] weekEnd = { DayOfWeek.Saturday, DayOfWeek.Sunday };
DateTime end = Enumerable.Range(0, int.MaxValue)
.Select(i => DateTime.Today.AddDays(i))
.Where(d => !weekEnd.Contains(d.DayOfWeek))
.Take(10)
.Last();

However, it returns 07/07, i assume because it includes today. I don't know if it is desired. If you don't want to include today change Range(0, int.MaxValue) to Range(1, int.MaxValue).

How to find End date from the given date and days excluding sundays

Try this for me:

var startDate = new DateTime(2012, 5, 3);
var sundaysOverDuration = 200 / 7;
var actualDuration = 200 + sundaysOverDuration;
var newDate = startDate.AddDays(actualDuration);

I also honestly have to admit that this link is flat out elegant surrounding how it handles a lot of the exceptions that exist when doing these types of calculations. I'm not sure you need something that complex, but it's worth letting you know. I'm going to inline the code just to ensure it's preserved if the link is ever broken.

public static double GetBusinessDays(DateTime startD, DateTime endD) 
{
double calcBusinessDays =
1 + ((endD-startD).TotalDays * 6 -
(startD.DayOfWeek-endD.DayOfWeek) * 2) / 7;
if ((int)startD.DayOfWeek == 0) calcBusinessDays --;
return calcBusinessDays;
}

public static DateTime AddWorkDaysToStartDate(DateTime startD, double businessDays)
{
int DoW = (int)startD.DayOfWeek;
double temp = businessDays + DoW + 1;
if (DoW != 0) temp --;
DateTime calcendD = startD.AddDays(
Math.Floor(temp / 6)*2-DoW + temp
- 2* Convert.ToInt32(temp % 6 == 0)) ;
}

Finally, based on your question it doesn't appear you need to handle holidays, but if you do the solution is much more complex and would need to be database driven, so just keep that in mind.

How to get 3 days back of current date and should not be weekends

This code assumes that if new date falls on a weekend, it will instead return the Friday before.

public static DateTime GetDateExcludeWeekends(DateTime date, int index)
{
var newDate = date.AddDays(-index);

if(newDate.DayOfWeek == DayOfWeek.Sunday)
{
return newDate.AddDays(-2);
}

if(newDate.DayOfWeek == DayOfWeek.Saturday)
{
return newDate.AddDays(-1);
}

return DateTime.Now;
}

You can tweak the logic, but the main thing is to look at the DayOfWeek enum property of the DateTime class.

How can I add business days to the current date in Java?

You may want to consider using ObjectLab Kit to do the heavy lifting for you.

Assuming the requirement is simply to return the next business day when the computed date falls on a non-business day:

package bizdays.example;

import java.time.LocalDate;
import java.util.HashSet;
import net.objectlab.kit.datecalc.common.DateCalculator;
import net.objectlab.kit.datecalc.common.DefaultHolidayCalendar;
import net.objectlab.kit.datecalc.common.HolidayHandlerType;
import net.objectlab.kit.datecalc.jdk8.LocalDateKitCalculatorsFactory;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;

public class BizDayTest {
private DateCalculator<LocalDate> dateCalculator;
private final LocalDate startDate = LocalDate.of(2009, 12, 23);

@Before
public void setUp() {
HashSet<LocalDate> holidays = new HashSet<LocalDate>();
holidays.add(LocalDate.of(2009, 12, 25)); // Friday

DefaultHolidayCalendar<LocalDate> holidayCalendar =
new DefaultHolidayCalendar<LocalDate>(holidays);

LocalDateKitCalculatorsFactory.getDefaultInstance()
.registerHolidays("example", holidayCalendar);
dateCalculator = LocalDateKitCalculatorsFactory.getDefaultInstance()
.getDateCalculator("example", HolidayHandlerType.FORWARD);
dateCalculator.setStartDate(startDate);
}

@Test
public void should_not_change_calendar_start_date_even_after_moving() {
assertThat(
dateCalculator.moveByBusinessDays(6).getStartDate(),
equalTo(startDate));
}

@Test
public void moveByBusinessDays_will_return_24_dec_2009_as_next_business_day() {
assertThat(
dateCalculator.moveByBusinessDays(1).getCurrentBusinessDate(),
equalTo(LocalDate.of(2009, 12, 24)));
}

@Test
public void moveByBusinessDays_will_return_28_dec_2009_as_two_business_days_later() {
assertThat(
dateCalculator.moveByBusinessDays(2).getCurrentBusinessDate(),
equalTo(LocalDate.of(2009, 12, 28)));

}

@Test
public void moveByDays_will_also_return_28_dec_2009_as_two_business_days_later() {
assertThat(
dateCalculator.moveByDays(2).getCurrentBusinessDate(),
equalTo(LocalDate.of(2009, 12, 28)));
}

@Test
public void moveByBusinessDays_will_exclude_25_26_and_27_dec_when_computing_business_days() {
assertThat(
dateCalculator.moveByBusinessDays(5).getCurrentBusinessDate(),
equalTo(LocalDate.of(2009, 12, 31)));
}

@Test
public void moveByDays_will_include_25_26_and_27_dec_when_computing_business_days() {
assertThat(
dateCalculator.moveByDays(5).getCurrentBusinessDate(),
equalTo(LocalDate.of(2009, 12, 28)));
}
}

The library defaults the working week to be from Monday to Friday, but you can change the defaults by supplying a custom WorkingWeek to DateCalculator's setWorkingWeek().

As shown in the last two examples, moveByDays() includes the weekends when moving the days, whereas moveByBusinessDays() excludes weekends.

The library also allows you to use java.util.Calendar or Joda Time's LocalDate. The examples use JDK8's java.time.LocalDate because it is the preferred way since JDK8.

Edit: Updated examples to use java.time.LocalDate

How to ignore weekends in date calculation

You can use the Fluent DateTime library easily.
Please refer to this Github library repository.
https://github.com/FluentDateTime/FluentDateTime

var dateTime = DateTime.Now.AddBusinessDays(5);

You can consider weekdays as BusinessDays



Related Topics



Leave a reply



Submit