Werktage / Arbeitstage eines Monats ermitteln

    • Offizieller Beitrag

    Hi,
    angeregt durch eine Fragestellung im H&U-Forum habe ich mal die folgende Funktion erstellt:
    _GetWorkDays($iMon=-1, $iYear=-1, $iRetType=6, $bHoliday=True)

    Für den übergebenen Monat des angegebenen Jahres (-1 jeweils aktueller(s) Monat/Jahr) wird in Abhängigkeit des RetTypes (5=Mo-Fr / 6=Mo-Sa / 7=Mo-So) folgendes ermittelt und in einem 2D-Array zurückgegeben:

    [0][0]= Anzahl Werktage im Monat
    [0][1]= "WeekNr erster Werktag / WeekNr letzter Werktag"

    [1][0]= Datum (Tag) des ersten Werktags
    [1][1]= Wochentag des ersten Werktags (0=Mo bis 6=So)
    [2..UBound-1][0]=weitere Werktage Datum (Tag)
    [2..UBound-1][0]=weitere Werktage Wochentag (0=Mo bis 6=So)

    Edit:
    Habe es nun doch erweitert, sodass die bundeseinheitlichen Feiertage berücksichtigt werden. Der Parameter kann bei Bedarf auf FALSE gesetzt werden.
    Die dazu erstellte Funktion: _IsHoliday($iMon, $iYear, $iDay) läßt sich natürlich auch gut für andere Anwendungen nutzen. Falls Feiertag, wird dessen Name zurückgegeben, anderenfalls ein Leerstring.

    _GetWorkDays( )
    [autoit]

    #include-once
    #include <Date.au3>
    ;===============================================================================
    ; Function Name: _GetWorkDays([$iMon=-1 [, $iYear=-1 [, $iRetType=6 [, $bHoliday=True]]]])
    ; Description:: Ermittelt alle Werktage eines Monats
    ; Parameter(s): $iMon Monat (Standard: -1, aktueller Monat)
    ; $iYear Jahr (Standard: -1, aktuelles Jahr), kleinster Wert: 1900
    ; $iRetType (5,6,7) Anzahl Werktage ab Mo (Standard: 6)
    ; $bHoliday True (Standard) berücksichtigt bundeseinheitliche Feiertage
    ; Requirement(s): #include <Date.au3>
    ; Return Value(s): 2D-Array
    ; [0][0]= Anzahl Werktage im Monat, [0][1]= "WeekNr erster Werktag / WeekNr letzter Werktag"
    ; [1][0]= Datum (Tag) des ersten Werktags,
    ; [1][1]= Wochentag des ersten Werktags (0=Mo bis 6=So)
    ; [n..UBound-1][0/1]=weitere Werktage Datum/Wochentag
    ; Author(s): BugFix ([email='bugfix@autoit.de'][/email])
    ;===============================================================================
    Func _GetWorkDays($iMon=-1, $iYear=-1, $iRetType=6, $bHoliday=True)
    If $iMon < 1 Or $iMon > 12 Then $iMon = @MON
    If $iYear < 1900 Then $iYear = @YEAR
    If $iRetType < 5 Or $iRetType > 7 Then $iRetType = 6
    Local $iDaysInMonth = _DateDaysInMonth($iYear, $iMon)
    Local $iWeekday, $aOut[1][2] = [[0,'']], $sWNr = ''
    Local $sFreeDay = 'N' ; 7 Werktage, ./. frei
    If $iRetType = 5 Then ; 5 Wertage, Sa/So frei
    $sFreeDay = '5 6'
    ElseIf $iRetType = 6 Then ; 6 Werktage, So frei
    $sFreeDay = '6'
    EndIf
    For $i = 1 To $iDaysInMonth
    $iWeekday = _DateToDayOfWeekISO($iYear, $iMon, $i)
    If StringInStr($sFreeDay, $iWeekday) Then ContinueLoop
    If $bHoliday And _IsHoliday($iYear, $iMon, $i) <> '' Then ContinueLoop
    $aOut[0][0] += 1
    If $aOut[0][0] = 1 Then $sWNr &= _WeekNumberISO($iYear, $iMon, $i)
    ReDim $aOut[UBound($aOut)+1][2]
    $aOut[UBound($aOut)-1][0] = $i
    $aOut[UBound($aOut)-1][1] = $iWeekday
    Next
    $aOut[0][1] = $sWNr & '/' & _WeekNumberISO($iYear, $iMon, $aOut[UBound($aOut)-1][0])
    Return $aOut
    EndFunc ;==>_GetWorkDays

    [/autoit] [autoit][/autoit] [autoit]

    Func _IsHoliday($iYear, $iMon, $iDay)
    Local $oHoliday = ObjCreate('Scripting.Dictionary')
    Local $HDays[32][2], $a, $b, $c, $d, $e, $H1, $H2, $N, $M
    Local $Easter, $EasterDate, $EasterDay, $EasterMonth, $RestJahr, $Tempyear
    ; fixe Feiertage bundesweit
    $oHoliday.Add($iYear & "/01/01", "Neujahr")
    $oHoliday.Add($iYear & "/05/01", "Maifeiertag")
    $oHoliday.Add($iYear & "/10/03", "Tag der Deutschen Einheit")
    $oHoliday.Add($iYear & "/12/25", "1. Weihnachtsfeiertag")
    $oHoliday.Add($iYear & "/12/26", "2. Weihnachtsfeiertag")
    ; variable Feiertage bundesweit
    $a = Mod($iYear, 19)
    $b = Mod($iYear, 4)
    $c = Mod($iYear, 7)
    $H1 = Int($iYear / 100)
    $H2 = Int($iYear / 400)
    $N = 4 + $H1 - $H2
    $M = 15 + $H1 - $H2 - Floor (Int((8 * $H1 + 13) / 25))
    $d = Mod((19 * $a + $M), 30)
    $e = Mod((2 * $b + 4 * $c + 6 * $d + $N), 7)
    If $d + $e = 35 Then
    $Easter = 50
    Else
    If $d = 28 And $e = 6 And $a > 10 Then
    $Easter = 49
    Else
    $Easter = 22 + $d + $e
    EndIf
    EndIf
    If $Easter < 32 Then
    $EasterDay = $Easter
    $EasterMonth = "03"
    Else
    $EasterDay = $Easter - 31
    $EasterMonth = "04"
    EndIf
    If $EasterDay < 10 Then
    $EasterDay = "0" & $EasterDay
    EndIf
    If $iYear < 1900 Then ; Datumsoperationen nur mgl. wenn > 1900 , Jahr wird konvertiert
    $RestJahr = Mod($iYear, 100)
    If _DateIsLeapYear($iYear) Then
    If $RestJahr < 10 Then
    $RestJahr = "0" & $RestJahr
    EndIf
    $Tempyear = 20 & $RestJahr
    Else
    If $RestJahr < 10 Then
    $RestJahr = "0" & $RestJahr
    EndIf
    $Tempyear = 19 & $RestJahr
    EndIf
    $EasterDate = $Tempyear & "/" & $EasterMonth & "/" & $EasterDay
    Else
    $EasterDate = $iYear & "/" & $EasterMonth & "/" & $EasterDay
    EndIf
    $oHoliday.Add(_DateAdd( 'd', -2, $EasterDate) , "Karfreitag")
    $oHoliday.Add($EasterDate , "Ostersonntag")
    $oHoliday.Add(_DateAdd( 'd', 1, $EasterDate) , "Ostermontag")
    $oHoliday.Add(_DateAdd( 'd', 39, $EasterDate) , "Christi Himmelfahrt")
    $oHoliday.Add(_DateAdd( 'd', 49, $EasterDate) , "Pfingstsonntag")
    $oHoliday.Add(_DateAdd( 'd', 50, $EasterDate) , "Pfingstmontag")
    If $oHoliday.Exists($iYear & '/' & $iMon & '/' & $iDay) Then
    Return $oHoliday.Item($iYear & '/' & $iMon & '/' & $iDay)
    Else
    Return ''
    EndIf
    EndFunc ;==>_IsHoliday

    [/autoit]
  • Wie wäre es denn mit einen 3D-Array?

    [Tag][Wochentag][Feiertag incl. Arbeitstag]
    01.01.2001 = [01012010][Freitag][X]
    02.01.2010 = [02012010[Samstag][]
    03.01.2010 = [03012010][Sonntag][]
    04.01.2010 = [04012010][Montag][]
    usw.


    Aber Deine UDF ist schön gewurden !!!

    Lieben Gruß,
    Alina

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Geheime Information: ;)
    OuBVU5ebLhHu5QvlnAyQB4A7SzBrvWulwL7RLl2BdH5tI6sIYspeMKeXMSXl

  • Um ein korrektes Ergebnis mit AutoIt v3.3.6.1 zu bekommen, ist eine Anpassung der UDF notwendig.
    Ich war mal so frei und habe dies direkt eingetragen (rote Markierung) und Zeile 14, 26+28.

    Gruß
    dvmade

    may the source be with you