Как определить последний рабочий день в данном месяце?

Как я могу вычислить последний рабочий день месяца в .NET?

Ответы

Ответ 1

Я бы сделал это так в течение недели с понедельника по пятницу:

var holidays = new List<DateTime>{/* list of observed holidays */};
DateTime lastBusinessDay = new DateTime();
var i = DateTime.DaysInMonth(year, month);
while (i > 0)
{
  var dtCurrent = new DateTime(year, month, i);
  if(dtCurrent.DayOfWeek < DayOfWeek.Saturday && dtCurrent.DayOfWeek > DayOfWeek.Sunday && 
   !holidays.Contains(dtCurrent))
    {
      lastBusinessDay = dtCurrent;
      i = 0;
    }
    else
    {
      i = i - 1;
    }
}

Ответ 2

Предполагая, что рабочие дни будут понедельника по пятницу (это не учитывает праздники), эта функция должна вернуть правильный ответ:

Function GetLastBusinessDay(ByVal Year As Integer, ByVal Month As Integer) As DateTime
    Dim LastOfMonth As DateTime
    Dim LastBusinessDay As DateTime

    LastOfMonth = New DateTime(Year, Month, DateTime.DaysInMonth(Year, Month))

    If LastOfMonth.DayOfWeek = DayOfWeek.Sunday Then 
        LastBusinessDay = LastOfMonth.AddDays(-2)
    ElseIf LastOfMonth.DayOfWeek = DayOfWeek.Saturday Then
        LastBusinessDay = LastOfMonth.AddDays(-1)
    Else
        LastBusinessDay = LastOfMonth
    End If

    Return LastBusinessDay

End Function

Ответ 3

Сначала вы получите последний день месяца. Затем продолжайте уменьшаться до тех пор, пока вы не начнете начало месяца или не нажмете дату, которая будет считаться "рабочим днем".

Ответ 4

Я мог бы подумать об этом простом коде С#, который дает вам последний рабочий день текущего месяца. Это займет только субботу или воскресенье в качестве праздников. Местные праздники, предназначенные для конкретной страны, должны обрабатываться вручную.

private DateTime GetLastBusinessDayOfCurrentMonth()
{
    var lastDayOfCurrentMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month,  DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month));

    if(lastDayOfCurrentMonth.DayOfWeek == DayOfWeek.Sunday)
        lastDayOfCurrentMonth = lastDayOfCurrentMonth.AddDays(-2);
    else if(lastDayOfCurrentMonth.DayOfWeek == DayOfWeek.Saturday)
        lastDayOfCurrentMonth = lastDayOfCurrentMonth.AddDays(-1);

    return lastDayOfCurrentMonth;
}

Ответ 5

общее назначение, псевдокод:

Day day = getLastDayOfMonth
int days = getDaysInMonth
for i = days to 0
  if day is weekday
    if day is not holiday
      return day
    end if
  end if
  day = prevDay
  days--
end for

throw exception because no business day was found in the month

Ответ 6

Использование LINQ:

   public static DateTime GetLastBussinessDayCurrentMonth(DateTime[] holidays)
   {
        DateTime todayDateTime = DateTime.Today;

        return
            Enumerable.Range(1, DateTime.DaysInMonth(todayDateTime.Year, todayDateTime.Month))
                .Select(day => new DateTime(todayDateTime.Year, todayDateTime.Month, day))
                .Where(
                    dt =>
                    dt.DayOfWeek != DayOfWeek.Sunday && dt.DayOfWeek != DayOfWeek.Saturday
                    && (holidays == null || !holidays.Any(h => h.Equals(dt))))
                .Max(d => d.Date);
   }

Объясняя

Создание списка целых чисел со всеми доступными в месяце днями

      Enumerable.Range(1, DateTime.DaysInMonth(todayDateTime.Year, todayDateTime.Month))

Фильтрация только дней, которые не падают в выходные и не падают на праздники

            .Where(
                dt =>
                dt.DayOfWeek != DayOfWeek.Sunday && dt.DayOfWeek != DayOfWeek.Saturday
                && (holidays == null || !holidays.Any(h => h.Equals(dt))))

Создать новое дат-время с отфильтрованными датами

            .Select(day => new DateTime(todayDateTime.Year, todayDateTime.Month, day))

            .Max(d => d.Date);

Ответ 7

Я придумал дополнительный метод, который можно использовать для получения ближайшего предыдущего или текущего рабочего дня, который затем может быть использован для получения последнего рабочего дня месяца - это также учитывается, если вы корректируете выходные дни

public static DateTime LastBusinessDayInMonth(int year, int month, bool adjustForWeekend = true)
{
    var lastDay = DateTime.DaysInMonth(year, month);
    return PreviousOrCurrentBusinessDay(new DateTime(year, month, lastDay), adjustForWeekend);
}

public static DateTime PreviousOrCurrentBusinessDay(DateTime? beforeOrOnDate = null, bool adjustForWeekend = true)
{
    var fromDate = beforeOrOnDate ?? DateTime.Today;
    var year = fromDate.Year;
    var month = fromDate.Month;
    var day = fromDate.Day;
    var holidays = UsHolidays(fromDate.Year, true).ToList(); // defined below
    var dtCurrent = new DateTime(year, month, day);

    while (!(dtCurrent.DayOfWeek < DayOfWeek.Saturday && dtCurrent.DayOfWeek > DayOfWeek.Sunday && !holidays.Contains(dtCurrent)))
    {
        dtCurrent = dtCurrent.AddDays(-1);
    }
    return dtCurrent;
}

Я также использую праздничные дни в США в своих расчетах, которые я получаю из следующего кода, который я разработал, глядя на этот пост: http://geekswithblogs.net/wpeck/archive/2011/12/27/us-holiday-list-in-c.aspx

Здесь можно увидеть код:

public static IEnumerable<DateTime> UsHolidays(int year, bool adjustForWeekend)
{
    return new List<DateTime>()
    {
        NewYears(year, adjustForWeekend),
        MlkDay(year),
        PresidentsDay(year),
        GoodFriday(year),
        MemorialDay(year),
        IndependenceDay(year, adjustForWeekend),
        LaborDay(year),
        Thanksgiving(year),
        Christmas(year, adjustForWeekend),
    };
}

public static DateTime NewYears(int year, bool adjustForWeekend)
{
    //NEW YEARS 
    return adjustForWeekend ? AdjustForWeekendHoliday(new DateTime(year, 1, 1).Date) : new DateTime(year, 1, 1).Date;
}

public static DateTime MemorialDay(int year)
{
    //MEMORIAL DAY  -- last monday in May 
    var memorialDay = new DateTime(year, 5, 31);
    var dayOfWeek = memorialDay.DayOfWeek;
    while (dayOfWeek != DayOfWeek.Monday)
    {
        memorialDay = memorialDay.AddDays(-1);
        dayOfWeek = memorialDay.DayOfWeek;
    }
    return memorialDay.Date;
}

public static DateTime IndependenceDay(int year, bool adjustForWeekend)
{
    //INDEPENCENCE DAY 
    return adjustForWeekend ? AdjustForWeekendHoliday(new DateTime(year, 7, 4).Date) : new DateTime(year, 7, 4).Date;
}

public static DateTime LaborDay(int year)
{
    //LABOR DAY -- 1st Monday in September 
    var laborDay = new DateTime(year, 9, 1);
    var dayOfWeek = laborDay.DayOfWeek;
    while (dayOfWeek != DayOfWeek.Monday)
    {
        laborDay = laborDay.AddDays(1);
        dayOfWeek = laborDay.DayOfWeek;
    }
    return laborDay.Date;
}

public static DateTime Thanksgiving(int year)
{
    //THANKSGIVING DAY - 4th Thursday in November 
    var thanksgiving = (from day in Enumerable.Range(1, 30)
                        where new DateTime(year, 11, day).DayOfWeek == DayOfWeek.Thursday
                        select day).ElementAt(3);
    var thanksgivingDay = new DateTime(year, 11, thanksgiving);
    return thanksgivingDay.Date;
}

public static DateTime Christmas(int year, bool adjustForWeekend)
{
    return adjustForWeekend ? AdjustForWeekendHoliday(new DateTime(year, 12, 25).Date) : new DateTime(year, 12, 25).Date;
}

public static DateTime MlkDay(int year)
{
    //Martin Luther King Day -- third monday in January
    var MLKDay = new DateTime(year, 1, 21);
    var dayOfWeek = MLKDay.DayOfWeek;
    while (dayOfWeek != DayOfWeek.Monday)
    {
        MLKDay = MLKDay.AddDays(-1);
        dayOfWeek = MLKDay.DayOfWeek;
    }
    return MLKDay.Date;
}

public static DateTime PresidentsDay(int year)
{
    //President Day -- third monday in February
    var presDay = new DateTime(year, 2, 21);
    var dayOfWeek = presDay.DayOfWeek;
    while (dayOfWeek != DayOfWeek.Monday)
    {
        presDay = presDay.AddDays(-1);
        dayOfWeek = presDay.DayOfWeek;
    }
    return presDay.Date;
}

public static DateTime EasterSunday(int year)
{
    var g = year % 19;
    var c = year / 100;
    var h = (c - c / 4 - (8 * c + 13) / 25 + 19 * g + 15) % 30;
    var i = h - h / 28 * (1 - h / 28 * (29 / (h + 1)) * ((21 - g) / 11));

    var day = i - ((year + year / 4 + i + 2 - c + c / 4) % 7) + 28;
    var month = 3;

    if (day > 31)
    {
        month++;
        day -= 31;
    }

    return new DateTime(year, month, day);
}

public static DateTime GoodFriday(int year)
{
    return EasterSunday(year).AddDays(-2);
}

public static DateTime AdjustForWeekendHoliday(DateTime holiday)
{
    if (holiday.DayOfWeek == DayOfWeek.Saturday)
    {
        return holiday.AddDays(-1);
    }
    return holiday.DayOfWeek == DayOfWeek.Sunday ? holiday.AddDays(1) : holiday;
}

Ответ 8

Function GetLastDay(ByVal month As Int32, ByVal year As Int32) As Date
        Dim D As New Date(year, month, Date.DaysInMonth(year, month))
        For i As Integer = 0 To Date.DaysInMonth(year, month)
            Select Case D.AddDays(-i).DayOfWeek
                Case DayOfWeek.Saturday, DayOfWeek.Sunday 'Not a weekday
                Case Else  'Is a weekday.  Flag as first weekday found
                    Return D.AddDays(-i)
                    'you can add other code here which could also do a check for holidays or ther stuff since you have a proper date value to look at in the loop
            End Select
        Next
End Function

Ответ 9

В Excel нет необходимости создавать макрос или UDF для определения последнего рабочего дня в месяце, если нет необходимости использовать праздничный стол. В этом примере с обычной датой Excel, размещенной в "E3", введите следующую формулу:

= КОНМЕСЯЦ ($ E $ 3,0) -IF (ДЕНЬНЕД (КОНМЕСЯЦ ($ E $ 3,0), 2)> 5, ДЕНЬНЕД (КОНМЕСЯЦ ($ E $ 3,0), 2) -5, 0)

если бы вы применили имя диапазона к ячейке "E3", скажем, "eom_WD", формула была бы:

= КОНМЕСЯЦ (eom_WD, 0) -IF (ДЕНЬНЕД (КОНМЕСЯЦ (eom_WD, 0), 2)> 5, ДЕНЬНЕД (КОНМЕСЯЦ (eom_WD, 0), 2) -5, 0)

EOMONTH использует дату Excel, чтобы дать максимально возможный день в данном месяце. WEEKDAY показывает количество дней недели в трех возможных форматах.

Опять же, праздники не включены в эту формулу. Вы можете заметить, что используются только эти две встроенные функции Excel.

Ответ 10

Вот как найти последний день месяца в С#:

DateTime today = DateTime.Today;
DateTime endOfMonth = new DateTime(today.Year,
                                   today.Month,
                                   DateTime.DaysInMonth(today.Year,
                                   today.Month));

Источник