从今天开始查找接下来的5个工作日



我使用nager.date来确定一天是假日还是周末(周六和周日(
我需要提取5个工作日后的日期(从今天或任何其他日期开始(。

DateTime date1 = new DateTime(2019, 12, 23); 
int i = 0;

while ( i < 5)
{
if (DateSystem.IsPublicHoliday(date1, CountryCode.IT) || DateSystem.IsWeekend(date1, CountryCode.IT))
{
date1 = date1.AddDays(1); 
}
else 
{
date1= date1.AddDays(1);
i++;
}
}

这个代码的问题是,如果出现最后一个else,它会给我添加1天,但不做任何其他检查。

例如:
如果开始日期是2020年7月13日,结果将是2020年07月18日,正如您所看到的,是在周六。

我如何修改此代码以实现我的需求?

订单很重要。应该首先调用AddDays,在调用它之后,我们检查新的一天是否符合我们的标准。

注意:我已经重命名了i变量,所以它更清晰。

DateTime date1 = new DateTime(2019, 12, 23); 
int daysAdded = 0;
while (daysAdded < 5)
{
date1 = date1.AddDays(1);
if (!DateSystem.IsPublicHoliday(date1, CountryCode.IT) && !DateSystem.IsWeekend(date1, CountryCode.IT)) {
// We only consider laboral days
// laboral days: They are not holidays and are not weekends
daysAdded ++;
}
}

我总是试图推广我的解决方案,所以这里有一个启用LINQ的解决方案:

public bool IsWorkingDay(DateTime dt)
=> !DateSystem.IsPublicHoliday(dt) && !DateSystem.IsWeekend(dt);
public DateTime NextWorkingDay(DateTime dt)
{
dt = dt.AddDays(1);
while (!IsWorkingDay(dt))
dt = dt.AddDays(1);
return dt;
}
public IEnumerable<DateTime> WorkingDaysFrom(DateTime dt)
{
if (!IsWorkingDay(dt))
dt = NextWorkingDay(dt); // includes initial dt, remove if unwanted
while (true)
{
yield return dt;
dt = NextWorkingDay(dt);
}
}

这将从给定的日期到时间结束抽取工作日,然后使用LINQ获取您想要的数字:

var next5 = WorkingDaysFrom(DateTime.Today).Take(5).ToList();

以下是如何获得2020年所有工作日:

var working2020 = WorkingDaysFrom(new DateTime(2020, 1, 1))
.TakeWhile(dt => dt.Year == 2020)
.ToList();
DateTime date1 = new DateTime(2019, 12, 23); 
int i = 0;
while ( i < 5)
{
date1 = date1.AddDays(1); 
if (!DateSystem.IsPublicHoliday(date1, CountryCode.IT) && !DateSystem.IsWeekend(date1, CountryCode.IT)) 
{           
i++;
}
}

但我认为你需要一个DateTime[]来存储所有五天的

这是一种更好、更快的方法,无需使用第三方库。

DateTime nowDate = DateTime.Now;
DateTime expectedDate;
if (nowDate.DayOfWeek == DayOfWeek.Saturday)
{
expectedDate = nowDate.AddDays(6);
}
else if (nowDate.DayOfWeek == DayOfWeek.Sunday)
{
expectedDate = nowDate.AddDays(5);
}
else
{
expectedDate = nowDate.AddDays(7);
}

我思考了这个问题,并根据Lasse-v-Karlsen提出的LINQ建议,开发了这个代码,它给了你最大的灵活性:

void Main()
{       
// a list of public holidays
var holidays = new List<DateTime>() {new DateTime(2020,1,1), 
new DateTime(2020,12,24), new DateTime(2020,12,25), new DateTime(2020,12,26)};
// a function checking if the date is a public holiday
Func<DateTime, bool> isHoliday = (dt) => holidays.Any(a=>a==dt);

// the start date
var dt = new DateTime(2020, 07, 13);
// end date, 5 working days later
var endDate = GetWorkingDay(dt, 5, isHoliday);
// print it
Console.WriteLine(endDate?.ToString("yyyy-mm-dd"));
}
public DateTime? GetWorkingDay(DateTime dt, int skipWorkingDays = 0, 
Func<DateTime, bool> holidays=null)
{
if (holidays == null) holidays = (dt) => false;
IEnumerable<DateTime> NextWorkingDay(DateTime dt)
{
while (true)
{
var day = dt.DayOfWeek;
if (day != DayOfWeek.Saturday && day != DayOfWeek.Sunday 
&& !holidays.Invoke(dt)) yield return dt;
dt = dt.AddDays(1);
}
}
if (skipWorkingDays<0) return null;
if (skipWorkingDays==0) return NextWorkingDay(dt).First();
var nextXDays = NextWorkingDay(dt).Take(skipWorkingDays).ToList();
var endDate = nextXDays.OrderByDescending(d => d).First();
return endDate;
}

无论您是像本例中那样有一个公共假日列表,还是有一个来自库的函数告诉您某个日期是否为公共假日,都可以随意修改Lambda函数isHoliday。在您的情况下,它将被定义为:

Func<DateTime, bool> isHoliday = (dt) => DateSystem.IsPublicHoliday(dt, CountryCode.IT); 

最新更新