c#增加/减少工作日的日期时间

c#增加/减少工作日的日期时间,c#,datetime,C#,Datetime,我有一个场景,给定一个日期(DateTime),该日期加/减x天(通过DateTime.AddDays)必须加或减x工作日,即跳过周末和节假日。我怎样才能让它这样做?我应该实现自己的版本并将其附加到日历或其他东西上吗 您应该自己检查这一天是否正常工作,因为DateTime类无法知道今年哪些日子是假日:)您可能应该有一个假日数据库来检查,如果day加/减x的值等于数据库中的一个值,则添加/减去另一个值,因为不是每个人都有相同的假日 我建议您必须自己实现它,并在如下扩展方法中实现: public

我有一个场景,给定一个日期(
DateTime
),该日期加/减
x
天(通过
DateTime.AddDays
)必须加或减
x
工作日,即跳过周末和节假日。我怎样才能让它这样做?我应该实现自己的版本并将其附加到日历或其他东西上吗

您应该自己检查这一天是否正常工作,因为DateTime类无法知道今年哪些日子是假日:)

您可能应该有一个假日数据库来检查,如果day加/减x的值等于数据库中的一个值,则添加/减去另一个值,因为不是每个人都有相同的假日

我建议您必须自己实现它,并在如下扩展方法中实现:


public static class DateTimeExtensions
{
    public static DateTime AddWorkdays(this DateTime originalDate, int workDays)
    {
        DateTime tmpDate = originalDate;
        while (workDays > 0)
        {
            tmpDate = tmpDate.AddDays(1);
            if (tmpDate.DayOfWeek < DayOfWeek.Saturday && 
                tmpDate.DayOfWeek > DayOfWeek.Sunday &&
                !tmpDate.IsHoliday())
                workDays--;
        }
        return tmpDate;
    }

    public static bool IsHoliday(this DateTime originalDate)
    {
        // INSERT YOUR HOlIDAY-CODE HERE!
        return false;
    }
}

公共静态类DateTimeExtensions
{
公共静态DateTime AddWorkdays(此DateTime originalDate,int workDays)
{
DateTime tmpDate=原始日期;
而(工作日>0)
{
tmpDate=tmpDate.AddDays(1);
如果(tmpDate.DayOfWeekDayOfWeek.Sunday&&
!tmpDate.IsHoliday())
工作日--;
}
返回tmpDate;
}
公共静态bool IsHoliday(此日期时间原始日期)
{
//在这里插入您的假期代码!
返回false;
}
}
基于:

公共静态类DateTimeExtensions
{
公共静态DateTime AddWorkDays(此DateTime日期,int workingDays)
{
int方向=工作日<0?-1:1;
DateTime newDate=日期;
while(工作日!=0)
{
newDate=newDate.AddDays(方向);
如果(newDate.DayOfWeek!=DayOfWeek.Saturday&&
newDate.DayOfWeek!=DayOfWeek.Sunday&&
!newDate.IsHoliday())
{
工作日-=方向;
}
}
返回newDate;
}
公共静态bool IsHoliday(此日期时间日期)
{
//您可以从某个数据库或文件加载/缓存,而不是硬编码
日期时间[]节假日=
新日期时间[]{
新日期时间(2010年12月27日),
新日期时间(2010,12,28),
新日期时间(2011,01,03),
新日期时间(2011,01,12),
新日期时间(2011,01,13)
};
返回假期。包含(日期。日期);
}
}

我最近用了一点LINQ:

private DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays, ICollection<DateTime> holidays)
{
    var futureDate = fromDate;
    var daterange = Enumerable.Range(1, numberofWorkDays * 2);
    var dateSet = daterange.Select (d => futureDate.AddDays(d));
    var dateSetElim = dateSet.Except(holidays).Except(dateSet.Where( s =>s.DayOfWeek == DayOfWeek.Sunday).Except(dateSet.Where  (s=>s.DayOfWeek==DayOfWeek.Saturday) ));

    //zero-based array
    futureDate = dateSetElim.ElementAt(numberofWorkDays-1);
    return futureDate;
}
private DateTime CalculateFutureDate(DateTime from date,int numberofWorkDays,i采集假日)
{
var futureDate=fromDate;
var daterange=可枚举的范围(1,numberofWorkDays*2);
var dateSet=daterange.Select(d=>futureDate.AddDays(d));
var dateSetElim=dateSet.Except(假日)。Except(dateSet.Where(s=>s.DayOfWeek==DayOfWeek.Sunday)。Except(dateSet.Where(s=>s.DayOfWeek==DayOfWeek.Saturday));
//零基阵列
futureDate=dateSetElim.ElementAt(numberofWorkDays-1);
返回未来日期;
}

我花了一些时间来解决这个问题。。。我已经创建了一个DB表,我把它和我的假期一起拉入一个数组。。我不得不改变他的工作方式,使之与我一样工作

在我的例子中,如果第一天是周六,而我的workingDayCount=-1,我想把星期四往回推(因为我的日期不能在周末或假日……它必须是工作日……在这种情况下是星期五。)

Kev的密码可以传回一个星期天。。。下面的代码将把它带到上一个工作日(通常是星期五——除非星期五是假日,而星期四又是假日)

以下是如何填充阵列:

private Holidays[] PopulateArrayWithDates()
    {
        SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DBConn"].ConnectionString);
        DateTime[] dtHolidays = new DateTime[] { };
        string sql = @"SELECT HolDate, HolName FROM [Server].DBName.dbo.tblHolidays";
        SqlCommand ADDCmd = new SqlCommand(sql, con);
        DataTable table = new DataTable();
        DataTable tbl = new DataTable();
        Utilities.Holidays[] allRecords = null;

        using (var command = new SqlCommand(sql, con))
        {
            con.Open();
            using (var reader = command.ExecuteReader())
            {
                var list = new List<Holidays>();
                while (reader.Read())
                    list.Add(new Holidays { dtHoliday = reader.GetDateTime(0), Desc = reader.GetString(1) });
                allRecords = list.ToArray();
            }
        }
        return allRecords;
    }
private假日[]PopulateArrayWithDates()
{
SqlConnection con=新的SqlConnection(ConfigurationManager.ConnectionString[“DBConn”].ConnectionString);
DateTime[]dtHolidays=新的DateTime[]{};
字符串sql=@“从[Server].DBName.dbo.tblHolidays中选择HolDate、HolName”;
SqlCommand ADDCmd=新的SqlCommand(sql,con);
DataTable=新的DataTable();
DataTable tbl=新的DataTable();
Utilities.Holidays[]allRecords=null;
使用(var命令=新的SqlCommand(sql,con))
{
con.Open();
使用(var reader=command.ExecuteReader())
{
var list=新列表();
while(reader.Read())
Add(新假日{dtHoliday=reader.GetDateTime(0),Desc=reader.GetString(1)});
allRecords=list.ToArray();
}
}
返回所有记录;
}

我已经修改了前面的答案,使之更加实用。我在下面提供了两个解决方案,一个使用IEnumerable,另一个使用IObservable和Reactive扩展

使用IObservable

public static class DateTimeExtensions
{
    public static DateTime AddWorkDays(this DateTime date, int workingDays)
    {
        return Observable
            .Generate
                (date, arg => true, arg => arg.AddDays(workingDays < 0 ? -1 : 1), arg => arg)
            .Where(newDate =>
                (newDate.DayOfWeek != DayOfWeek.Saturday &&
                 newDate.DayOfWeek != DayOfWeek.Sunday &&
                 !newDate.IsHoliday()))
            .Take(Math.Abs(workingDays) + 1)
            .LastAsync()
            .Wait();
    }

    public static bool IsHoliday(this DateTime date)
    {
        return false;
    }
}
公共静态类DateTimeExtensions
{
公共静态DateTime AddWorkDays(此DateTime日期,int workingDays)
{
可观测回波
生成
(日期,arg=>true,arg=>arg.AddDays(工作日<0?-1:1),arg=>arg)
.Where(newDate=>
(newDate.DayOfWeek!=DayOfWeek.周六&&
newDate.DayOfWeek!=DayOfWeek.Sunday&&
!newDate.IsHoliday())
.Take(数学Abs(工作日)+1)
.LastAsync()
.Wait();
}
公共静态bool IsHoliday(此日期时间日期)
{
返回false;
}
}
使用IEnumerable

public static class DateTimeExtensions
{
    public static DateTime AddWorkDays(this DateTime date, int workingDays)
    {
        return date.GetDates(workingDays < 0)
            .Where(newDate =>
                (newDate.DayOfWeek != DayOfWeek.Saturday &&
                 newDate.DayOfWeek != DayOfWeek.Sunday &&
                 !newDate.IsHoliday()))
            .Take(Math.Abs(workingDays))
            .Last();
    }

    private static IEnumerable<DateTime> GetDates(this DateTime date, bool isForward)
    {
        while (true)
        {
            date = date.AddDays(isForward ? -1 : 1);
            yield return date;
        }
    } 

    public static bool IsHoliday(this DateTime date)
    {
        return false;
    }
}
公共静态类DateTimeExtensions
{
公共静态DateTime AddWorkDays(此DateTime日期,int workingDays)
{
返回日期。GetDates(工作日<0)
.Where(newDate=>
(newDate.DayOfWeek!=DayOfWeek.周六&&
newDate.DayOfWeek!=DayOfWeek.Sunday&&
!newDate.IsHoliday())
.Take(Math.Abs(工作日))
.Last();
}
私有静态IEnumerable GetDates(此日期时间日期,bool isForward)
{
while(true)
{
date=date.AddDays(isForwa
private Holidays[] PopulateArrayWithDates()
    {
        SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DBConn"].ConnectionString);
        DateTime[] dtHolidays = new DateTime[] { };
        string sql = @"SELECT HolDate, HolName FROM [Server].DBName.dbo.tblHolidays";
        SqlCommand ADDCmd = new SqlCommand(sql, con);
        DataTable table = new DataTable();
        DataTable tbl = new DataTable();
        Utilities.Holidays[] allRecords = null;

        using (var command = new SqlCommand(sql, con))
        {
            con.Open();
            using (var reader = command.ExecuteReader())
            {
                var list = new List<Holidays>();
                while (reader.Read())
                    list.Add(new Holidays { dtHoliday = reader.GetDateTime(0), Desc = reader.GetString(1) });
                allRecords = list.ToArray();
            }
        }
        return allRecords;
    }
public static class DateTimeExtensions
{
    public static DateTime AddWorkDays(this DateTime date, int workingDays)
    {
        return Observable
            .Generate
                (date, arg => true, arg => arg.AddDays(workingDays < 0 ? -1 : 1), arg => arg)
            .Where(newDate =>
                (newDate.DayOfWeek != DayOfWeek.Saturday &&
                 newDate.DayOfWeek != DayOfWeek.Sunday &&
                 !newDate.IsHoliday()))
            .Take(Math.Abs(workingDays) + 1)
            .LastAsync()
            .Wait();
    }

    public static bool IsHoliday(this DateTime date)
    {
        return false;
    }
}
public static class DateTimeExtensions
{
    public static DateTime AddWorkDays(this DateTime date, int workingDays)
    {
        return date.GetDates(workingDays < 0)
            .Where(newDate =>
                (newDate.DayOfWeek != DayOfWeek.Saturday &&
                 newDate.DayOfWeek != DayOfWeek.Sunday &&
                 !newDate.IsHoliday()))
            .Take(Math.Abs(workingDays))
            .Last();
    }

    private static IEnumerable<DateTime> GetDates(this DateTime date, bool isForward)
    {
        while (true)
        {
            date = date.AddDays(isForward ? -1 : 1);
            yield return date;
        }
    } 

    public static bool IsHoliday(this DateTime date)
    {
        return false;
    }
}
public static DateTime AddExcludingWeekends(this DateTime dateTime, int nDays)
{
  var wholeWeeks = nDays / 5; //since nDays does not include weekdays every week is considered as 5 days
  var absDays = Math.Abs(nDays);
  var remaining = absDays % 5; //results in the number remaining days to add or substract excluding the whole weeks
  var direction = nDays / absDays;//results in 1 if nDays is posisive or -1 if it's negative
  while (dateTime.DayOfWeek == DayOfWeek.Saturday || dateTime.DayOfWeek == DayOfWeek.Sunday)
    dateTime = dateTime.AddDays(direction); //If we are already in a weekend, get out of it
  while (remaining-- > 0)
  {//add remaining days...
    dateTime = dateTime.AddDays(direction);
    if (dateTime.DayOfWeek == DayOfWeek.Saturday)
      dateTime = dateTime.AddDays(direction * 2);//...skipping weekends
  }
  return dateTime.AddDays(wholeWeeks * 7); //Finally add the whole weeks as 7 days, thus skipping the weekends without checking for DayOfWeek
}
public class Program
{
    public static void Main(string[] args)
    {
        Double days= 7;
        string s=DateTime.Now.AddDays(7).ToString("dd/MM/yyyy");  
        DateTime dt= OrderDeliveryDate(days);
        Console.WriteLine("dt"+dt.ToString("dd/MM/yyyy"));


    }

    public static DateTime OrderDeliveryDate(Double days)
    {

        Double count=0;
        for(int i=0;i<days;i++)
        {
            if(DateTime.Now.AddDays(i).DayOfWeek.ToString() == "Saturday")
            {
               count= count+1;
            }
            else if(DateTime.Now.AddDays(i).DayOfWeek.ToString() == "Sunday")
            {
                count=count+1;
            }

        }
        days=days+count;
        return DateTime.Now.AddDays(days);
    }
}
    public static DateTime AddBussinessDays(this DateTime originalDate, int workDays)
    {
        if (workDays == 0)
        {
            return originalDate;
        }

        originalDate = originalDate.AddDays(workDays);

        if (originalDate.IsHoliday() || originalDate.DayOfWeek == DayOfWeek.Saturday || originalDate.DayOfWeek == DayOfWeek.Sunday)
        {
            return originalDate.AddBussinessDays(workDays < 0 ? -1 : 1);
        }

        return originalDate;
    }