【问题标题】:Find next 5 working days starting from today从今天开始查找接下来的 5 个工作日
【发布时间】:2020-07-16 09:44:33
【问题描述】:

我使用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 年 7 月 18 日结束,如您所见,是星期六。

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

【问题讨论】:

  • 创建一个像这样的 bool 方法: bool EveryoneAtHome(Datetime myDateTime) 如果 IsPublicHoliday 或 IsWeekend 返回 true。然后你可以在你的 while 循环中调用这个方法,如果为 false 则添加 1 天
  • 我无法使用方法或函数,因为我在“UiPath”中使用此代码,并且不允许创建这些东西。只有原始代码。
  • 使用 LINQ:public IEnumerable&lt;DateTime&gt; WorkingDaysFrom(DateTime dt) { while (true) { if (...) yield return dt; dt = dt.AddDays(1); } } 然后var next5 = WorkingDaysFrom(...).Take(5).ToList();

标签: c# date


【解决方案1】:

顺序很重要。 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 ++;
    }
}

【讨论】:

    【解决方案2】:

    我总是尝试概括我的解决方案,所以这里有一个启用 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();
    

    【讨论】:

      【解决方案3】:
      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[] 来存储所有五天

      【讨论】:

        【解决方案4】:

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

        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);
        }
        

        【讨论】:

        • ...但是你没有公共假期。
        • @MartinBackasch ,这没关系,因为公共假期会随着时间的推移而变化,并且在某些国家/地区会有所不同,所以这是一个更普遍的答案
        • 我不评价它,但我认为这很重要,因为问题本身已经说明了。
        • 恕我直言 OP 将失去检查假期的好处。对于与假期无关的情况,您的答案是一个很好的答案。
        • 现实生活中没有不可知的场景。在意大利,每年都会有一些假期,正如@Martin 所说,问题本身已经说明了,所以不,我不能忽略它们。
        【解决方案5】:

        我考虑了问题,根据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); 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-04
          • 1970-01-01
          • 1970-01-01
          • 2011-01-28
          • 1970-01-01
          • 2012-11-30
          相关资源
          最近更新 更多