isHoliday() ; USA holidays

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
tidbit
Posts: 1272
Joined: 29 Sep 2013, 17:15
Location: USA

isHoliday() ; USA holidays

Post by tidbit » 14 Jun 2020, 12:15

isHoliday()

Download|Screenshot

Version 1.0, By: tidbit

Do whatever you want with it


Description:
Budgii on IRC needed a way to count business days. Checking weekends is easy enough, but theres not an easy way to check if a day is a holiday, especially if that holiday has a shifting date, such as Easter* or Memorial Day. This solves that!
Now you have no excuse for missing an event
* holy crap, whoever figured out that algorithm in 1876 is crazy

Feel free to modify, share lists of other non-USA based holidays.

Features:
  • Many Holidays - See below*
  • Business Days Only - Holiday lands on a weekend? don't fetch it
  • Fetch the first found - Don't loop through the whole list, just stop at the first. Save those precious nanoseconds
  • Revolutionary TDML (tidbit date markup language) Date format. in the format of ["month day-day dayName", "Day Text", federal/business day]
  • RETURNS - State-of-the-art String-based technology returns all** the holidays of the specified date as a newline delimited list!
*

Code: Select all

New Year's Day
Martin Luther King Jr. Day
Presidents Day
Easter Sunday
Easter Monday
Memorial Day
Fourth of July
Labor Day
Columbus Day
Veterans Day
Thanksgiving Day
Christmas Eve
Christmas Day
Valentines Day
Mother's Day
Father's Day
St. Patrick's Day
Halloween
0123 Day
Pi Day
Tau Day
May the fourth be with you
1111 Day
50% through the year
** Based on parameters set. Results may vary. Offer ends when Gregorian Calendar is no longer valid. Does not predict future holidays that don't exist as of Sun June 14, 2020

Examples:

Code: Select all

Example:
msgbox % isHoliday("20201111000000")

; returns:
; "Veterans Day
; 1111 Day"

; ------------

; Example:
msgbox % isHoliday("20200413131536")

; returns:
; "Easter Monday"
rawr. fear me.
*poke*
Is it December 21, 2012 yet?

User avatar
Spawnova
Posts: 554
Joined: 08 Jul 2015, 00:12
Contact:

Re: isHoliday() ; USA holidays

Post by Spawnova » 14 Jun 2020, 12:40

This is pretty cool, I could definitely find some use for this, thanks for sharing!

User avatar
joedf
Posts: 8953
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: isHoliday() ; USA holidays

Post by joedf » 14 Jun 2020, 22:35

Neat work as always! :thumbup:
Also, interesting fine-prints. :think: ;)
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]

garry
Posts: 3763
Joined: 22 Dec 2013, 12:50

Re: isHoliday() ; USA holidays

Post by garry » 16 Jun 2020, 16:30

thank you tidbit
if you go to Germany ... ( it's allowed again since 15'th june 2020 ( was lockdown because covid-19 ) )
german holidays from user 'haichen' , func feiertage(jahr,land,timestrg)
https://www.autohotkey.com/boards/viewtopic.php?f=10&t=61733

User avatar
kunkel321
Posts: 1047
Joined: 30 Nov 2015, 21:19

Re: isHoliday() ; USA holidays

Post by kunkel321 » 31 May 2023, 08:38

Thanks for this excellent function Tidbit. It got used here: viewtopic.php?f=76&t=117399&p=524196#p524196

fyi also, There's a typo in Halloween's date... Should be "10 31" rather than "8 31".
ste(phen|ve) kunkel

User avatar
Chunjee
Posts: 1419
Joined: 18 Apr 2014, 19:05
Contact:

Re: isHoliday() ; USA holidays

Post by Chunjee » 01 Jun 2023, 15:56

Juneteenth is a federal holiday now

tidbit wrote:
14 Jun 2020, 12:15
State-of-the-art String-based technology
lol

User avatar
kunkel321
Posts: 1047
Joined: 30 Nov 2015, 21:19

Re: isHoliday() ; USA holidays

Post by kunkel321 » 02 Jun 2023, 11:44

Chunjee wrote:
01 Jun 2023, 15:56
Juneteenth is a federal holiday now
From the Wikipedia article:
... According to the bill, federal government employees will now get to take the day off every year on June 19, or should the date fall on a Saturday or Sunday, they will get the Friday or Monday closest to the Saturday or Sunday on which the date falls respectively.
I think the "if weekend, Mon or Fri, whichever is closest" part is a new algorithm -- yes? I don't think any other holidays work like that(?)

EDIT: I suppose the math for that should be pretty straight-forward... If day = Sat, minus one, if day = Sun, plus one, else, don't change.
ste(phen|ve) kunkel

User avatar
kunkel321
Posts: 1047
Joined: 30 Nov 2015, 21:19

Re: isHoliday() ; USA holidays

Post by kunkel321 » 07 Jun 2023, 11:38

Actually... Regarding Juneteenth, I think Tidbit's function can already handle it, if you enter the dates as I have done in the code here. For the embeded "20 year report" I temporarily commented-out Tau Day and Father's Day.

EDIT: It occurs to me that having param2 = 1 would also filter out everything from June, other than the Juneteenth items. Like this:
If (isHoliday(mydate, 1, 0) <> "") {
Also, it appears to be okay to comment-out some of the holidays, if you don't want to use them. But be mindful of the extra set of [brackets] enclosing the entire array of holidays.

Code: Select all

#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
; #singleInstance, off
#singleInstance, force

/*
date:=A_Now
date:=20200704121212
date:=20200120333333
date:=20191128333333

; easter
; date:=20200412000000 ; Sunday, not affecting business day
date:=20200413000000 ; month, affects business day

; date:=20201111000000

; msgbox % isHoliday(date)
; msgbox % isHoliday(date,, 1)
msgbox % isHoliday(date, 1)
exitapp

~esc::
	exitapp
return
*/

/*
Name: isHoliday
Version 1.0 (Thursday, June 11, 2020)
Created: ]Thursday, June 11, 2020
Author: tidbit
Credit: internet

yyyymmddhhmiss   = a valid timestamp in this format
businessOnly     = [0 = default] if '0', returns a list of all todays events. otherwise only checks important holidays
stopAtFirst      = [0 = default] if '0', returns all dates in a newline delimited list. Otherwise it stops at the first item found

Description:
	is today a USA holiday? A business/federal holiday? Yes? cool, now you know. No? now you know!

Example:
	msgbox % isHoliday("20201111000000")
	returns:
		"Veterans Day
		1111 Day"
Example:
	msgbox % isHoliday("20200413000000")
	returns:
		"Easter Monday"
*/

/*
---------------------------
IsHoliday - Copy.ahk
---------------------------
  For Month 06

2023 Jun 19 Mon: Juneteenth
2024 Jun 19 Wed: Juneteenth
2025 Jun 19 Thu: Juneteenth
2026 Jun 19 Fri: Juneteenth
2027 Jun 18 Fri: Juneteenth
2028 Jun 19 Mon: Juneteenth
2029 Jun 19 Tue: Juneteenth
2030 Jun 19 Wed: Juneteenth
2031 Jun 19 Thu: Juneteenth
2032 Jun 18 Fri: Juneteenth
2033 Jun 20 Mon: Juneteenth
2034 Jun 19 Mon: Juneteenth
2035 Jun 19 Tue: Juneteenth
2036 Jun 19 Thu: Juneteenth
2037 Jun 19 Fri: Juneteenth
2038 Jun 18 Fri: Juneteenth
2039 Jun 20 Mon: Juneteenth
2040 Jun 19 Tue: Juneteenth
2041 Jun 19 Wed: Juneteenth
2042 Jun 19 Thu: Juneteenth

---------------------------
OK
---------------------------
*/

!+1::
; This month, 20 years
myyear := 2023
mymonth := 06
daysinmonth := 30 ; approximate number is fine...
monthreport := "  For Month " . mymonth . "`n`n"
loop, 20 {
	mydate := myyear . mymonth . "01000000"
	loop, %daysinmonth% {
		If (isHoliday(mydate) <> "") {
			FormatTime, myfdate, %mydate%, yyyy MMM dd ddd
			monthreport .= myfdate . ": " . isHoliday(mydate) . "`n"
		}
		mydate += 1, D
	}
	myyear++
}
MsgBox, % monthreport
ExitApp

!+2::
; All holidays this year
tyyear := A_Year
tydate := tyyear . "0101000000"

tyreport := "  For Year " . tyyear . "`n`n"
loop, 365 {
	If (isHoliday(tydate) <> "") {
		FormatTime, ftydate, %tydate%, ddd MMM dd

		tyreport .= ftydate . ": " . isHoliday(tydate) . "`n"
	}
	tydate += 1, D
}
MsgBox, % tyreport
ExitApp

;=================================================================
isHoliday(yyyymmddhhmiss:="", businessOnly:=0, stopAtFirst:=0)
{
	tstamp:=(yyyymmddhhmiss="") ? A_Now : yyyymmddhhmiss

	; not a valid timestamp
	if (strLen(yyyymmddhhmiss)!=14)
		return -1
	if yyyymmddhhmiss is not number
		return -2

	date={}
	out:="" ; return a string of all possible events today

	; grab more data than needed. safety first.
	formatTime, ttt, %tstamp%, yyyy|MM|dd|MMMM|dddd
	date:=strSplit(ttt, "|")
	formatTime, ttt, %tstamp%, YWeek
	date.push(substr(ttt, 5))
	formatTime, ttt, %tstamp%, YDay
	date.push(ttt)

	date:={year: date[1], mon: date[2], day: date[3], monN: date[4], dayN: date[5], dayY: date[7], weekY: date[6]}

	; Leap-year
	isLeap:=0
	if ((mod(date.year, 4)=0 && mod(date.year, 100)!=0) || mod(date.year, 400)=0)
		isLeap:=1

	; Easter... Amazing. Thank you, "Nature" Journal - 1876
	a:=mod(date.year, 19), b:=floor(date.year/100), c:=mod(date.year, 100)
	d:=floor(b/4), e:=mod(b, 4), f:=floor((b+8)/25)
	g:=floor((b-f+1)/3), h:=mod(((19*a)+b-d-g+15), 30), i:=floor(c/4),
	k:=mod(c, 4), l:=mod((32+(2*e)+(2*i)-h-k), 7), m:=floor((a+(11*h)+(22*L))/451)
	emonth:=format("{:02}", (floor((h+l+(7*m)+114)/31)))
	eday:=format("{:02}", mod((h+l-(7*m)+114), 31)+1)

	; single space delimited, strictly
	; ["month day-day dayName", "Day Text", federal/business day]
	; if "dayName" = "absolute", "month" becomes "isLeapYear", and "day-day" is a number between 1-366
	dates:=[["01 01", "New Year's Day", 1]
	, ["01 15-21 Monday", "Martin Luther King Jr. Day", 1]
	, ["02 15-21 Monday", "Presidents Day", 1]
	, [ emonth " " eday, "Easter Sunday", 0]
	, [ emonth " " eday+1, "Easter Monday", 1]
	, ["05 25-31 Monday", "Memorial Day", 1]
	, ["07 04", "Fourth of July", 1]
	, ["09 01-07 Monday", "Labor Day", 1]
	, ["10 08-14 Monday", "Columbus Day", 1]
	, ["11 11", "Veterans Day", 1]
	, ["11 22-28 Thursday", "Thanksgiving Day", 1]
	, ["12 24", "Christmas Eve", 0]
	, ["12 25", "Christmas Day", 1]
	, ["02 14", "Valentines Day", 0]
	, ["05 08-14 Sunday", "Mother's Day", 0]
	, ["06 15-21 Sunday", "Father's Day", 0]
	, ["03 17", "St. Patrick's Day", 0]
	, ["10 31", "Halloween", 0]
	, ["01 23", "0123 Day", 0]
	, ["03 14", "Pi Day", 0]
	, ["06 28", "Tau Day", 0]
	, ["06 20 Monday", "Juneteenth", 1]
	, ["06 19 Monday", "Juneteenth", 1]
	, ["06 19 Tuesday", "Juneteenth", 1]
	, ["06 19 Wednesday", "Juneteenth", 1]
	, ["06 19 Thursday", "Juneteenth", 1]
	, ["06 19 Friday", "Juneteenth", 1]
	, ["06 18 Friday", "Juneteenth", 1]
	, ["05 04", "May the fourth be with you", 0]
	, ["11 11", "1111 Day", 0]
	, ["0 182 absolute", "50% through the year", 0]
	, ["1 183 absolute", "50% through the year", 0]]

	stop:=0
	for k, day in dates
	{
		if (day[3]=0 && businessOnly=1)
			continue

		holiday:=day[2] ; give it a nicer name
		stamp:=strSplit(day[1], " ")
		range:=strSplit(stamp[2], "-")
		range[2]:=(range[2]="") ? range[1] : range[2]

		if (stamp[3]!="absolute")
		{
			; set a temp var to blank if a weekday wasn't specified.
			; Otherwise check if the specified day is today
			ttt:=(stamp[3]="") ? "" : date.dayN
			isBetween:=(date.day>=range[1] && date.day<=range[2]) ? 1 : 0
			if (date.mon=stamp[1] && isBetween=1 && ttt=stamp[3])
				out.=holiday "`n", stop:=1
		}
		else
		{
			if (isLeap=stamp[1] && date.dayY=stamp[2])
				out.=holiday "`n", stop:=1
		}

		if (stopAtFirst=1 && stop=1) ; sometimes you'll want to be a nanosecond faster.
			return trim(out, "`r`n `t")
	}
	return trim(out, "`r`n `t")
}

ste(phen|ve) kunkel

User avatar
kunkel321
Posts: 1047
Joined: 30 Nov 2015, 21:19

Re: isHoliday() ; USA holidays

Post by kunkel321 » 25 Oct 2023, 13:27

Hi there @tidbit, or anyone. Have you converted this to AHK v2 code? EDIT 12-24-2023. See next reply.
Last edited by kunkel321 on 24 Dec 2023, 14:17, edited 1 time in total.
ste(phen|ve) kunkel

User avatar
kunkel321
Posts: 1047
Joined: 30 Nov 2015, 21:19

Re: isHoliday() ; USA holidays

Post by kunkel321 » 24 Dec 2023, 14:17

If anyone wants an AHK v2 version of this, Just Me converted it, as part of a larger project. Look here: viewtopic.php?f=82&t=123895&p=552302#p552302
ste(phen|ve) kunkel

Post Reply

Return to “Scripts and Functions (v1)”