Как рассчитать рабочие дни между датами

У меня простая проблема, но я уже пробовал ее решить несколькими способами и не получил ожидаемого результата. Мне нужно посчитать количество рабочих дней между двумя датами, но без учета первого дня.

Пример: начальная_дата: 08.15.2024 (четверг) Final_date: 20.08.2024 (вторник)

В Excel, если я рассчитаю календарные дни =DAYS(dt_initial;dt_final), я получу в общей сложности 5 дней. Другими словами, считается суббота и воскресенье, но это не то, что мне нужно. Если я попытаюсь не учитывать выходные =DIAWORKALHOTAL.INTL(dt_initial;dt_final;1), я получу результат 4. То есть он включает в себя 15-е число в счете.

Мне бы хотелось найти способ считать со следующего дня, то есть в приведенном выше примере результат будет = 3 (дни 16, 19 и 20).

Если кто-нибудь знает способ решить эту проблему, будь то в Excel, PowerBI или даже с помощью Python, не могли бы вы сообщить мне?

Как я уже упоминал, в Excel я уже пробовал использовать =DIAWORKALHOTAL.INTL(dt_initial;dt_final;1), но он возвращает счетчик с учетом начальной даты (первый день).

В PowerBI я попробовал приведенный ниже пример, но столкнулся с той же проблемой:

рабочие_дни = ЧИСТРАБДНИ(таблица[начальная_дата],таблица[конечная_дата], 1)

Привет, вопросы по Stack Overflow должны быть на английском языке, но вы можете задать их на испанском здесь: es.stackoverflow.com

cybernetic.nomad 22.08.2024 21:53
=DIAWORKALHOTAL.INTL(dt_initial + 1;dt_final;1),
Scott Craner 22.08.2024 21:58

Спасибо :) Но мне кажется это не совсем работает. Пример: Начальная дата: 19.08.24 (понедельник) Конечная дата: 21.08.2024 (среда) Применяя эту логику, результат: 2 (это хорошо, потому что в данном случае результат — это то, что я хочу). Но посмотрим на другой пример: Начальная дата: 19.08.24 (понедельник) Конечная дата: 20.08.2024 (вторник) Применяя логику +1, результат: 0, верно? Но правильным является 1. Другой пример: Начальная дата: 19.08.24 (понедельник) Конечная дата: 19.08.2024 (понедельник) Тот же день, поэтому правильный результат равен 0. Но применив логику +1, результат будет быть -1

jessie 22.08.2024 23:40

Что произойдет, если первое свидание, например, суббота? с 24.8.24 по 26.8.24? Каков будет ожидаемый результат?

Ike 23.08.2024 08:49

@jessie, ты хотя бы попробовал =DIAWORKALHOTAL.INTL(dt_initial + 1;dt_final;1), прежде чем ответить на комментарий? =DIAWORKALHOTAL.INTL(date(2024, 8, 19)+ 1;date(2024, 8, 20);1) вернет 1, а не ноль. =DIAWORKALHOTAL.INTL не рассчитывает «длительность», а просто возвращает количество дней, удовлетворяющих определенному условию (рабочий день). поэтому =DIAWORKALHOTAL.INTL(date(2024, 8, 20);date(2024, 8, 20);1) вернет 1. но я согласен, если дата начала > дата окончания, DIAWORKALHOTAL.INTL не будет работать.

rachel 23.08.2024 10:09

@Джесси - отличный вопрос, кстати. См. ответ ниже - это самый экономный (простой) способ дать правильный ответ (для начала = конца того же дня и т. д.), который я пока вижу (но через etfc может быть получено больше).

JB-007 23.08.2024 16:40
Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
1
6
99
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Ниже/здесь ссылка:

=IF(C4<C3,"",NETWORKDAYS(C3,C4)-(WEEKDAY(C3,2)<=5))

Причина, по которой другие вычисления не работали (те, что в комментариях и т. д.), в первую очередь связана с несколько «милым» подходом, заключающимся в попытке игнорировать первый день, установив дату начала += 1 (день после даты начала).

Как вы заметили, это падает, когда начало = конец. Мой подход решает эту проблему (и более обобщенные варианты) надлежащим/правильным образом, а в остальном он столь же прост/экономичен в использовании/настройке.


Чтобы продемонстрировать, что это правильное решение, приведена таблица результатов (на основе таблицы данных/доступна по ссылке выше) в диапазоне дат начала/окончания.


К вашему сведению - не уверен, откуда взялась функция OPs, приведенная ниже, но сказал, что Excel/Python и т. д. также будут приветствоваться. Я придерживался Excel (судя по названию ☺)


Результат поиска Google для функции, предоставленной OP/первым комментатором.

(обратите внимание, что ссылки AI ссылаются на этот конкретный пост!)


Я считаю, что вам просто нужно это:

=NETWORKDAYS.INTL(dt_initial, dt_final,1)-NETWORKDAYS.INTL(dt_initial,dt_initial,1)

NETWORKDAYS.INTL(dt_initial, dt_final,1) рассчитывает рабочие дни между начальной и конечной датой включительно.

NETWORKDAYS.INTL(dt_initial,dt_initial,1) проверяет, является ли initial_date рабочим днем ​​или нет, если да, вычтите единицу из NETWORKDAYS.INTL(dt_initial, dt_final,1), если нет, оставьте NETWORKDAYS.INTL(dt_initial, dt_final,1) как есть.

Вы можете использовать мою функцию DateDiffWorkdays:

Date1 = #2024-08-19#
Date2 = #2024-08-20#
? DateDiffWorkdays(Date1, Date2)
 1 

Date1 = #2024-08-19#
Date2 = #2024-08-21#
? DateDiffWorkdays(Date1, Date2)
 2 

Date1 = #2024-08-15#
Date2 = #2024-08-20#
? DateDiffWorkdays(Date1, Date2)
 3 

Функция:

' Returns the count of full workdays between Date1 and Date2.
' The date difference can be positive, zero, or negative.
' Optionally, if WorkOnHolidays is True, holidays are regarded as workdays.
'
' Note that if one date is in a weekend and the other is not, the reverse
' count will differ by one, because the first date never is included in the count:
'
'   Mo  Tu  We  Th  Fr  Sa  Su      Su  Sa  Fr  Th  We  Tu  Mo
'    0   1   2   3   4   4   4       0   0  -1  -2  -3  -4  -5
'
'   Su  Mo  Tu  We  Th  Fr  Sa      Sa  Fr  Th  We  Tu  Mo  Su
'    0   1   2   3   4   5   5       0  -1  -2  -3  -4  -5  -5
'
'   Sa  Su  Mo  Tu  We  Th  Fr      Fr  Th  We  Tu  Mo  Su  Sa
'    0   0   1   2   3   4   5       0  -1  -2  -3  -4  -4  -4
'
'   Fr  Sa  Su  Mo  Tu  We  Th      Th  We  Tu  Mo  Su  Sa  Fr
'    0   0   0   1   2   3   4       0  -1  -2  -3  -3  -3  -4
'
' Execution time for finding working days of three years is about 4 ms.
'
' Requires table Holiday with list of holidays.
'
' 2015-12-19. Gustav Brock. Cactus Data ApS, CPH.
'
Public Function DateDiffWorkdays( _
    ByVal Date1 As Date, _
    ByVal Date2 As Date, _
    Optional ByVal WorkOnHolidays As Boolean) _
    As Long
    
    Dim Holidays()      As Date
    
    Dim Diff            As Long
    Dim Sign            As Long
    Dim NextHoliday     As Long
    Dim LastHoliday     As Long
    
    Sign = Sgn(DateDiff("d", Date1, Date2))
    If Sign <> 0 Then
        If WorkOnHolidays = True Then
            ' Holidays are workdays.
        Else
            ' Retrieve array with holidays between Date1 and Date2.
            Holidays = DatesHoliday(Date1, Date2, False) 'CBool(Sign < 0))
            ' Ignore error when using LBound and UBound on an unassigned array.
            On Error Resume Next
            NextHoliday = LBound(Holidays)
            LastHoliday = UBound(Holidays)
            ' If Err.Number > 0 there are no holidays between Date1 and Date2.
            If Err.Number > 0 Then
                WorkOnHolidays = True
            End If
            On Error GoTo 0
        End If
        
        ' Loop to sum up workdays.
        Do Until DateDiff("d", Date1, Date2) = 0
            Select Case Weekday(Date1)
                Case vbSaturday, vbSunday
                    ' Skip weekend.
                Case Else
                    If WorkOnHolidays = False Then
                        ' Check for holidays to skip.
                        If NextHoliday <= LastHoliday Then
                            ' First, check if NextHoliday hasn't been advanced.
                            If NextHoliday < LastHoliday Then
                                If Sgn(DateDiff("d", Date1, Holidays(NextHoliday))) = -Sign Then
                                    ' Weekend hasn't advanced NextHoliday.
                                    NextHoliday = NextHoliday + 1
                                End If
                            End If
                            ' Then, check if Date1 has reached a holiday.
                            If DateDiff("d", Date1, Holidays(NextHoliday)) = 0 Then
                                ' This Date1 hits a holiday.
                                ' Subtract one day to neutralize the one
                                ' being added at the end of the loop.
                                Diff = Diff - Sign
                                ' Adjust to the next holiday to check.
                                NextHoliday = NextHoliday + 1
                            End If
                        End If
                    End If
                    Diff = Diff + Sign
            End Select
            ' Advance Date1.
            Date1 = DateAdd("d", Sign, Date1)
        Loop
    End If
    
    DateDiffWorkdays = Diff

End Function

Для этого требуются некоторые вспомогательные функции — слишком много кода, чтобы публиковать здесь — все их можно найти в модулях моего репозитория на GitHub: VBA.Date.

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

Я добавил для вас демо-версию Excel в папку demos: DateWork.xlsm.

Другие вопросы по теме