title: Cron expression to skip only public holidays of the year
body: <p>I've a ASP.Net MVC application, We are using calender control to pick the date on UI. We are using cron expression to set the public holiday date. My requirement is Date picker on UI should not allow user to select public holidays date that are set using cron expression. I would like to verify if my cron expression is correct or not. If its correct what's the problem with my C# code. My function is not returning valid dates. Its returning holidays also as a part of valid dates.</p>
  
  <p>Following are the list of holidays I need to skip - New Year, Memorial Day, Independence Day, Labor Day, Thanksgiving, Day after thanksgiving,Chrismas Evening, Chrismas.</p>
  
  <p>Appreciate your help ! Below the code and cron expression, At the end of GetDate function I'm trying to get valid date.
  I'm looking for cron expression of just public holidays (Not Weekends, Not vacations). </p>
  
  <pre><code>List&lt;DateTime&gt; GetDates(DateTime cutOffDate, bool isAlways = false, string Code = null, string TestMethod = null)
          {
              var validDates = new List&lt;DateTime&gt;();
              try
              {
                  List&lt;string&gt; cronExpressionStrings = new List&lt;string&gt;();
                  cronExpressionStrings.Add("0 0 0 1 1 ? *"); // New Year Day
                  cronExpressionStrings.Add("0 0 0 ? 5 MON#4 *"); //Memorial Day
                  cronExpressionStrings.Add("0 0 0 4 7 ? *"); //Independence Day
                  cronExpressionStrings.Add("0 0 0 ? 9 MON#1"); //Labor Day
                  cronExpressionStrings.Add("0 0 0 ? 11 THU#4 *");//Thanksgiving
                  cronExpressionStrings.Add("0 0 0 ? 11 FRI#4 *");//Day after Thanksgiving
                  cronExpressionStrings.Add("0 0 0 24 12 ? *"); //Chrismas Evening
                  cronExpressionStrings.Add("0 0 0 25 12 ? *"); //Chrismas
  
                  var currentDateTimeWithPaddingDays = AddPaddingDaysToDate(DateTime.UtcNow);
  
                  if (cronExpressionStrings?.Count &gt; 0)
                  {
                      foreach (string cronExpressionString in cronExpressionStrings)
                      {
                          var cronExpression = new CronExpression(cronExpressionString);
  
                          //If the first padded date is the same as the first Cron date then add that day to valid days
                          var firstCronDate = cronExpression.GetNextValidTimeAfter(DateTime.UtcNow);
                          if (firstCronDate.Value.Date == currentDateTimeWithPaddingDays.Date)
                          {
                              if (!validDates.Contains(currentDateTimeWithPaddingDays.Date))
                              {
                                  validDates.Add(currentDateTimeWithPaddingDays.ToUniversalTime().Date);
                              }
                          }
  
                          DateTimeOffset? currentDateTimeWithPaddingDaysOffset = currentDateTimeWithPaddingDays;
  
                          //If no drop down padding days were used, then get next Cron date
                          if (currentDateTimeWithPaddingDays.Date == DateTime.UtcNow.Date)
                          {
                              currentDateTimeWithPaddingDaysOffset = cronExpression.GetNextValidTimeAfter(currentDateTimeWithPaddingDays).Value;
                          }
  
                          for (var dateTimeOffset = currentDateTimeWithPaddingDaysOffset;
                               (dateTimeOffset?.Date &lt; cutOffDate.Date);)
                          {
                              if (!validDates.Contains(dateTimeOffset.Value.Date))
                              {
                                  validDates.Add(dateTimeOffset.Value.Date);
                              }
  
                              dateTimeOffset = cronExpression.GetNextValidTimeAfter(dateTimeOffset.Value).Value;
                          }
                      }
                  }
                  else
                  {
                      var dateOnly = new DateTime(currentDateTimeWithPaddingDays.Year, currentDateTimeWithPaddingDays.Month, currentDateTimeWithPaddingDays.Day);
  
                      validDates.AddRange(Enumerable.Range(0, 1 + cutOffDate.Subtract(dateOnly).Days)
                                                    .Select(offset =&gt; dateOnly.AddDays(offset))
                                                    .ToArray());
                  }
              }
              catch (Exception ex)
              {
                  log.Error("test", ex);
                  throw;
              }
  
              return validDates.OrderBy(d =&gt; d).ToList();
          }
  
  
  private DateTime AddPaddingDaysToDate(DateTime date)
          {
              try
              {
                  var groupName = DropDownGroupName.PaddingMatrix.ToString();
                  var paddingMatrix = (from b in context.DropDownValue.AsNoTracking()
                                       join d in context.DropDownGroup.AsNoTracking() on b.TableCode equals d.ID
                                       where d.TableName == groupName
                                       select new DropDownValueArgs
                                       {
                                           ID = d.ID,
                                           Name = b.Name,
                                           Value = b.Value,
                                           Description = b.Description,
                                           RegionCode = b.RegionCode
                                       }).ToList();
                  if (paddingMatrix.Count &gt; 0)
                  {
                      var paddingdays = paddingMatrix.Where(z =&gt; string.Equals(z.Name, date.Hour.ToString(), StringComparison.InvariantCultureIgnoreCase) &amp;&amp; string.Equals(z.RegionCode, date.DayOfWeek.ToString(), StringComparison.InvariantCultureIgnoreCase)).Select(z =&gt; z.Value).FirstOrDefault();
                      date = date.AddDays(double.Parse(paddingdays, System.Globalization.CultureInfo.InvariantCulture));
                  }
              }
              catch (Exception ex)
              {
                  log.Error("AddPaddingDaysToDate()", ex);
                  throw;
              }
  
              return date;
          }
  </code></pre>