#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 (bugfix@autoit.de)
;===============================================================================
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

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
