Local Calendar for a trigger

Is there a way to trigger an event for say President's Day locally? Not Google.

IE The 3rd Monday of February every year?

Thanks!

Yes, here are two creative ways you can use existing features to make that happen:

1 Like

Thanks...I'll play with this a bit tomorrow to see how it works!!!

There is a ical device handler you can use too. Itā€™s not really a ā€œtriggerā€ but this is how i use it to trigger automations.

https://raw.githubusercontent.com/Mark-C-uk/Hubitat/master/ical

2 Likes

Where are the docs for this driver? I managed to get one of my calendars populating a Dashboard cell, but unable to add another calendar. I simply used a ";" between the calendars, but I get a Error 500. No clue to format a Conditions using it, however.

I found the original thread on this, but it isn't very informative.

Any further info @mark.cockcroft ?

From looking at the code iā€™d recommend using 1 calendar feed per device.

The device is pretty basic, i did post an example on how to use conditions using RM. Considering the age of the device i doubt anyone is supporting it. It works for me in my use case but feel free to update it so that it works for you in yours.

1 Like

I wrote a simple app that figures out a bunch of holidays. I use it for my exterior lighting and it sets a global variable that my lighting app uses. When my lights come on at dusk they check the variable to see if it is currently a holiday. You could use that same variable to trigger a rule.

Since I use it for lighting some of the holidays are setup for a single day and some for several days or a couple of weeks (Christmas lighting). It is fairly easy to setup holidays and change the ranges.

	if (month == 11) {
		if (today[Calendar.WEEK_OF_MONTH] == 4) {
			if (today[Calendar.DAY_OF_WEEK] > 2) {
				holiday = "Thanksgiving"
			}
		}
	}
	if (dateBetween("12/1", "12/30", today)) {
		holiday = "Christmas"
	}
	if (dateBetween("12/31", "12/31", today)) {
		holiday = "New Years"
	}

For example, New Year's is a single day but Christmas is for the whole month. Some of them were a bit challenging to figure out since the day varies, like Thanksgiving. Easter and the first day of spring were also a bit odd since they don't follow an easy pattern.

I'm sure there is an easier way to do this but it is what I did a few years ago. There is also a holiday app by somebody in the community but I haven't looked into it, You are welcome to use this if you would find it useful. It wouldn't be hard to add and remove holidays.

1 Like

Thanks to all...

lairdknox

This looks like exactly what I'm looking for...and will check out the Holiday App as well. It is the moving Holidays that are the real problem. Thanks!

Here's the code. I don't have it published anywhere. It is pretty basic, let me know if you have any questions.

/*
* Author: Jeff Knox
* Platform: Hubitat
*
* Copyright 2023 Jeff Knox

* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
*	http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*/

definition(
	name: "What Holiday Is It?",
	namespace: "jlkSpace",
	author: "Jeff Knox",
	description: "App to set the global holiday variable",
	category: "My Apps",
	iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
	iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")

preferences {
	page(name: "mainPage", title: "What Holiday is it?", install: true, uninstall: true) {
		section("") {
			input "holidayName", "capability.sensor", required: true, title: "Select holiday global variable connector."
		}
	}
}

def installed() {
	initialize()
}

def updated() {
	unsubscribe()
	initialize()
}

def initialize() {
	log.debug "ā€¢ā€¢ā€¢ INIT ā€¢ā€¢ā€¢"
	subscribe(location, "sunrise", sunriseHandler)
	schedule('0 0 1 ? * * *', sunriseHandler)
}

def dateBetweenOrig(Date date1, Date date2, Date toCheck) {
	// not inclusive of 2nd date
	return toCheck.after(date1) && toCheck.before(date2)
}

def dateBetween(String date1, String date2, Date toCheck) {
	// inclusive
	def year = new Date()[Calendar.YEAR]
	def d1 = new Date(date1 + "/" + year)
	def d2 = new Date(date2 + "/" + year) + 1

	return toCheck.after(d1) && toCheck.before(d2)
}


def sunriseHandler(evt) {
	
	log.debug "ā€¢ā€¢ā€¢ Checking holiday list ā€¢ā€¢ā€¢"

	def holiday = "Just another day"
	def today = new Date()
	def day = today[Calendar.DAY_OF_MONTH]
	def month = today[Calendar.MONTH] + 1
	def year = today[Calendar.YEAR]
	def dateStr = (today[Calendar.MONTH] + 1) + "/" + today[Calendar.DAY_OF_MONTH] + "/" + today[Calendar.YEAR]

	if (dateBetween("3/17", "3/17", today)) {
		holiday = "St Patrick"
	}

	switch (dateStr) {
		case "4/4/2021":
		case "4/17/2022":
		case "4/9/2023":
		case "3/31/2024":
		case "4/20/2025":
		case "4/5/2026":
		case "3/28/2027":
		case "4/16/2028":
		case "4/1/2029":
		case "4/21/2030":
		case "4/13/2031":
		case "3/28/2032":
		case "4/17/2033":
		case "4/9/2034":
		case "3/25/2035":
		case "4/13/2036":
		case "4/5/2037":
		case "4/25/2038":
		case "4/10/2039":
		case "4/1/2040":
		case "4/21/2041":
		case "4/6/2042":
		case "3/29/2043":
		case "4/17/2044":
		case "4/9/2045":
		case "3/25/2046":
		case "4/14/2047":
		case "4/5/2048":
		case "4/18/2049":
		case "4/10/2050":
		holiday = "Easter"
		break

		case "3/20/2021":
		case "3/20/2022":
		case "3/20/2023":
		case "3/19/2024":
		case "3/20/2025":
		case "3/20/2026":
		case "3/20/2027":
		case "3/19/2028":
		case "3/20/2029":
		case "3/20/2030":
		case "3/20/2031":
		case "3/19/2032":
		case "3/20/2033":
		case "3/20/2034":
		case "3/20/2035":
		case "3/19/2036":
		case "3/19/2037":
		case "3/20/2038":
		case "3/20/2039":
		case "3/19/2040":
		case "3/19/2041":
		case "3/20/2042":
		case "3/20/2043":
		case "3/19/2044":
		case "3/19/2045":
		case "3/20/2046":
		case "3/20/2047":
		case "3/19/2048":
		case "3/19/2049":
		case "3/20/2050":
		holiday = "Spring"
		break

	}

	if (month == 5) {
		if (day > 24 && today[Calendar.DAY_OF_WEEK] == 1) {
			holiday = "Memorial Day"
		}
	}

	if (dateBetween("7/1", "7/5", today)) {
		holiday = "Forth"
	}

	if (month == 9) {
		if (day < 8 && today[Calendar.DAY_OF_WEEK] == 1) {
			holiday = "Labor Day"
		}
	}

	if (dateBetween("10/27", "10/31", today)) {
		holiday = "Halloween"
	}
	if (month == 11) {
		if (today[Calendar.WEEK_OF_MONTH] == 4) {
			if (today[Calendar.DAY_OF_WEEK] > 2) {
				holiday = "Thanksgiving"
			}
		}
	}
	if (dateBetween("12/1", "12/30", today)) {
		holiday = "Christmas"
	}
	if (dateBetween("12/31", "12/31", today)) {
		holiday = "New Years"
	}
	if (dateBetween("1/1", "1/2", today)) {
		holiday = "New Years"
	}
	
	holidayName.setVariable(holiday)
}

You can setup a simple holiday with an if statement.

	if (dateBetween("12/31", "12/31", today)) {
		holiday = "New Years"
	}

Just put in your date range and set the variable value.

Some of them got a little more complicated. Labor Day uses both the month and day of the week to get the first Monday of September.

	if (month == 9) {
		if (day < 8 && today[Calendar.DAY_OF_WEEK] == 1) {
			holiday = "Labor Day"
		}
	}

For Easter and the first day of spring I used a case statement that just contains all the dates out to 2050.

One odd thing I see in the code is that I appear to be triggering it twice. This is unneeded and I expect it is a leftover of some testing.

	subscribe(location, "sunrise", sunriseHandler)
	schedule('0 0 1 ? * * *', sunriseHandler)

On the plus side it shows how to use both a scheduled event and a subscribed event. In this case the first one triggers at sunrise and the second at 1 am. I only use the values between dusk and midnight so it didn't matter in my use case.

To use it just setup a Hub Variable to store the value.

Then create a connector for that variable. The connectors are old but I haven't refactored the code to use the newer formats. Once you have the connector you can select it in the app.

One you have this setup the variable will be set each day depending one when you have it scheduled. Then you can use it in Rule Machine as a trigger or variable in an action.

Let me know if you have any questions or need help modifying the holidays.

Wow...THANKS! That's awesome!

Just wanted to say thanks again...I could not have asked for anything better. It's exactly what I was looking for! THANKS!

That's great! It is a bit of a hack but it has been running for a few years now. I forget about it and sometimes I'm surprised when I go outside and the exterior lights are in a holiday mode.