#include-once
#include <Date.au3>
;===============================================================================
; Function Name:   _IsHoliday($iYear, $iMon=-1, $iDay=-1)
; Description::    Prüft ob übergebenes Datum ein (bundeseinheitlicher) Feiertag ist
; Parameter(s):    $iYear  das Jahr des Datums (ab 1900) ODER
;                          das gesamte Datum als String "JJJJ/MM/TT"
;                  $iMon   der Monat des Datums (wenn $iYear kein GesamtDatumString)
;                  $iDay   der Tag des Datums (wenn $iYear kein GesamtDatumString)
; Requirement(s):  #include <Date.au3>
; Return Value(s): Erfolg
;                       ist Feiertag  - der Name des Feiertags
;                       kein Feiertag - ein Leerstring
;                  Fehler
;                       0  @error=1   - Datum nicht existent
; Note:            der Funktion können regionale und eigene Feiertage zugefügt werden
; Author(s):       BugFix (bugfix@autoit.de)
;===============================================================================
Func _IsHoliday($iYear, $iMon=-1, $iDay=-1)
	Local $aDate = StringRegExp($iYear, '(\d{4})/(\d{1,2})/(\d{1,2})', 3)
	If Not @error Then
		$iYear = $aDate[0]
		$iMon = $aDate[1]
		$iDay = $aDate[2]
	EndIf
	If $iYear < 1900 Or $iMon < 1 Or $iMon > 12 Or $iDay < 1 Or $iDay > 31 Then Return SetError(1,0,0)
	$iMon = StringRight('0' & $iMon, 2)
	$iDay = StringRight('0' & $iDay, 2)
	If Not _DateIsValid($iYear & '/' & $iMon & '/' & $iDay) Then Return SetError(1,0,0)
	Local $oHoliday = ObjCreate('Scripting.Dictionary')
	Local $HDays[32][2], $a, $b, $c, $d, $e, $H1, $H2, $N, $M
	Local $Easter, $EasterDate, $EasterDay, $EasterMonth, $PfSoDat
	; 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
	$EasterDate = $iYear & "/" & $EasterMonth & "/" & $EasterDay
	$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")
	$PfSoDat = _DateAdd( 'd', 50, $EasterDate)
	$oHoliday.Add($PfSoDat, "Pfingstmontag")
#region - fixe und variable Feiertage regional <== Bei Bedarf aktivieren
#cs
	Local $MutterDat, $4AdvDat
	; Muttertag = 2. Sonntag im Mai ABER wenn Pfingsten = 2.Sonntag im Mai dann ist Muttertag am 1. Sonntag
	; Der 2. Sonntag kann nur zw. dem 8. u. 14.5. liegen
	For $maitag = 8 To 14
		If _DateToDayOfWeek($iYear, 5, $maitag) = 1 Then
			If $maitag < 10 Then
				$maitag = "0" & $maitag
			EndIf
			$MutterDat = $iYear & "/05/" & $maitag
			If $MutterDat = $PfSoDat Then
				$MutterDat = _DateAdd( 'd', -7, $iYear & "/05/" & $maitag)
			EndIf
			ExitLoop
		EndIf
	Next
	$oHoliday.Add($MutterDat, "Muttertag")
	; Erntedankfest 1. Sonntag im Oktober (zw. 1. u. 7.10.)
	For $oktobertag = 1 To 7
		If _DateToDayOfWeek($iYear, 10, $oktobertag) = 1 Then
			$oktobertag = "0" & $oktobertag
			$oHoliday.Add($iYear & "/10/" & $oktobertag, "Erntedankfest")
			ExitLoop
		EndIf
	Next
	; 4.Advent = Sonntag vor 25.12. (zw. 18. u. 24.12.)
	For $deztag = 18 To 24
		If _DateToDayOfWeek($iYear, 12, $deztag) = 1 Then
			$4AdvDat = $iYear & "/12/" & $deztag
			$oHoliday.Add(_DateAdd( 'd', -7, $4AdvDat), "3. Advent")
			$oHoliday.Add(_DateAdd( 'd', -14, $4AdvDat), "2. Advent")
			$oHoliday.Add(_DateAdd( 'd', -21, $4AdvDat), "1. Advent")
			$oHoliday.Add(_DateAdd( 'd', -28, $4AdvDat), "Totensonntag")
			$oHoliday.Add(_DateAdd( 'd', -32, $4AdvDat), "Buß- und Bettag")
			ExitLoop
		EndIf
	Next
	$oHoliday.Add(_DateAdd( 'd', -52, $EasterDate), "Weiberfastnacht")
	$oHoliday.Add(_DateAdd( 'd', -48, $EasterDate), "Rosenmontag")
	$oHoliday.Add(_DateAdd( 'd', -47, $EasterDate), "Fastnacht")
	$oHoliday.Add(_DateAdd( 'd', -46, $EasterDate), "Aschermittwoch")
	$oHoliday.Add(_DateAdd( 'd', -3, $EasterDate), "Gründonnerstag")
	$oHoliday.Add(_DateAdd( 'd', -1, $EasterDate), "Ostersamstag")
	$oHoliday.Add(_DateAdd( 'd', 60, $EasterDate), "Fronleichnam")
	$oHoliday.Add($iYear & "/01/06", "Heilige Drei Könige")
	$oHoliday.Add($iYear & "/02/14", "Valentinstag")
	$oHoliday.Add($iYear & "/10/31", "Reformationstag")
	$oHoliday.Add($iYear & "/11/01", "Allerheiligen")
	$oHoliday.Add($iYear & "/12/24", "Heiligabend")
	$oHoliday.Add($iYear & "/12/31", "Silvester")
	$oHoliday.Add($4AdvDat, "4. Advent")
	; ######### Hier können weitere eigene Feiertage eingetragen werden #############
	;	$oHoliday.Add('JJJJ/MM/TT', 'Name des Feiertags')   <== MUSTER

	; ###############################################################################
#ce
#endregion
	If $oHoliday.Exists($iYear & '/' & $iMon & '/' & $iDay) Then
		Return $oHoliday.Item($iYear & '/' & $iMon & '/' & $iDay)
	Else
		Return ''
	EndIf
EndFunc   ;==>_IsHoliday
