Sign in to follow this  
Followers 0
BugFix

Is date an holiday?

5 posts in this topic

I've made an function to check if given date is an holiday.

Because different countries have different holidays i've used the most known holidays for check. You can use also other defined dates inside function if needed. Or you add own holidays. ;)

You can give the date as (year, mon, day) or as ("YYYY/MM/DD") and let mon and day free.

#include-once
#include <Date.au3>
;===============================================================================
; Function Name:   _IsHoliday($iYear, $iMon=-1, $iDay=-1)
; Description::    Checks if given date is an holiday
; Parameter(s):    $iYear  year of date (as from 1900) OR
;                          entire date as string "YYYY/MM/DD"
;                  $iMon   month of date (if $iYear not entire date)
;                  $iDay   day of date (if $iYear not entire date)
; Requirement(s):  #include <Date.au3>
; Return Value(s): Success
;                       is Holiday    - name of holiday
;                       isn't Holiday - blank string
;                  Failure
;                       0  @error=1   - date isn't valid
; Note:            you can insert own days as holiday
; 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
    ; fix days
    $oHoliday.Add($iYear & "/01/01", "New Year's Day")
    $oHoliday.Add($iYear & "/05/01", "May Day")
    $oHoliday.Add($iYear & "/12/25", "Christmas Day")
    $oHoliday.Add($iYear & "/12/26", "Boxing Day")
    ; variable days
    $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) , "Good Friday")
    $oHoliday.Add($EasterDate , "Easter Sunday")
    $oHoliday.Add(_DateAdd( 'd', 1, $EasterDate) , "Easter Monday")
    $oHoliday.Add(_DateAdd( 'd', 39, $EasterDate) , "Ascension Thursday")
    $oHoliday.Add(_DateAdd( 'd', 49, $EasterDate) , "Whitsunday")
    $PfSoDat = _DateAdd( 'd', 50, $EasterDate)
    $oHoliday.Add($PfSoDat, "Whit Monday")
#region - other days that may be an holiday, activate if needed
#cs
    Local $MutterDat, $4AdvDat
    ; Mother's Day = 2. Sunday of May BUT if Whit = 2. Sunday of May than Mother's Day at 1. Sunday
    ; 2. Sunday only between 8. and 14.5.
    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, "Mother's Day")
    ; Thanksgiving  1. Sunday of October (between 1. and 7.10.)
    For $oktobertag = 1 To 7
        If _DateToDayOfWeek($iYear, 10, $oktobertag) = 1 Then
            $oktobertag = "0" & $oktobertag
            $oHoliday.Add($iYear & "/10/" & $oktobertag, "Thanksgiving")
            ExitLoop
        EndIf
    Next
    ; 4.advent = Sunday before 25.12. (between 18. and 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), "Sunday before Advent on which the dead are commemorated")
            $oHoliday.Add(_DateAdd( 'd', -32, $4AdvDat), "Day of Prayer and Repentance")
            ExitLoop
        EndIf
    Next
    $oHoliday.Add(_DateAdd( 'd', -48, $EasterDate), "Monday before Lent")
    $oHoliday.Add(_DateAdd( 'd', -47, $EasterDate), "Shrove Tuesday")
    $oHoliday.Add(_DateAdd( 'd', -46, $EasterDate), "ash wednesday")
    $oHoliday.Add(_DateAdd( 'd', -3, $EasterDate), "Holy Thursday")
    $oHoliday.Add(_DateAdd( 'd', 60, $EasterDate), "Corpus Christi")
    $oHoliday.Add($iYear & "/01/06", "Epiphany")
    $oHoliday.Add($iYear & "/02/14", "Valentine's Day")
    $oHoliday.Add($iYear & "/10/31", "Reformation Day")
    $oHoliday.Add($iYear & "/11/01", "All Saints' Day")
    $oHoliday.Add($iYear & "/12/24", "Christmas Eve")
    $oHoliday.Add($iYear & "/12/31", "New Year's Eve")
    $oHoliday.Add($4AdvDat, "4. Advent")
    ; ######### Here you can insert own holidays #######################
    ;   $oHoliday.Add('YYYY/MM/DD', 'Name of holiday')   <== SAMPLE

    ; ##################################################################
#ce
#endregion
    If $oHoliday.Exists($iYear & '/' & $iMon & '/' & $iDay) Then
        Return $oHoliday.Item($iYear & '/' & $iMon & '/' & $iDay)
    Else
        Return ''
    EndIf
EndFunc   ;==>_IsHoliday

_IsHoliday.au3


Best Regards BugFix  

Share this post


Link to post
Share on other sites



Great stuff, I shall be using this in one of my projects.

Thanks for sharing.

Share this post


Link to post
Share on other sites

Just out of curiosity; What does using a Dictionary get you that an Array doesn't in this case? Is it any more efficient (before I bother testing performance)?

Share this post


Link to post
Share on other sites

What does using a Dictionary get you that an Array doesn't in this case?

At first i've solved it with an array. Creation of an array is faster than an dictionary object. But i also need an fast check if date is in collection. And here wins the dictionary object. ObjDict.Exists(Item) is very faster than an array search. Thats my experience.


Best Regards BugFix  

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0