'Tis The Season (Almost)

Ok, I’m the worlds biggest Grinch in November, but I’m festive as heck in December, so I’d like to have this ready by then. I want to write a rule to operate the Christmas lights, but obviously only if it’s between 2 specific days (Dec 1 and Jan 7). I thought about a simple CRON rule to toggle a “Christmas” switch on those two dates, and let the other rules run only when “Christmas” is ON, but I’d like something that can be run on startup, and check if it’s between those days. Sounds pretty simple, buy I’m not overly familiar with DateTime. I’m wondering what kind of solutions everyone’s come up with.


I found a solution!

Would be great if you could share it with us.

Sorry, was up late tweaking the system.

if(now.getMonthOfYear == 12 || now.getMonthOfYear== 1){                           
           if(now.getMonthOfYear == 12 || now.getDayOfMonth < 8){            
                      sendCommand(christmasLights, ON)                              
                       sendCommand(christmasLights, OFF)                             
             sendCommand(christmasLights, OFF)                                     

Are your lights on all day during this period? I’m not knocking you for writing a rule, it’s a good concept for say season-based heating schedules, but seems a bit extreme for flipping a switch and leaving it for 2 months.

Heck no! I don’t have the money to burn that kind of electricity. The outside lights come on at sunset, and turn off at 11. The tree lights come on at sunset, but only when I’m at home, and turn off at bedtime.

To simplify my main code, I run the above at startup, and on dec 1 and Jan 8, and toggle a virtual switch. Then in the main code, I simply need to run if(Christmas.state == ON). Just for fun, I also change the label of the living room plug to “Christmas Tree”, if the virtual switch is on.

1 Like

If you have other places where you may want to apply this sort of thing, you might be interested in the Time of Day Design Pattern:

The tl;dr is you have a String Item which represents state and a rule or rules to calculate the state. In your rules that care they just check the state to see what it should do. I’ve found a String is better primarily because once you have more than a couple of states maintaining Switches becomes challenging.

1 Like

Oh, wow! That sounds like it could be VERY useful. I might have to play around with it during Christmas break. I’m guessing, requiring a string item to make the data available system-wide, that there’s no way to use some sort of array to record multiple states? Say if(ToD[1] == “Dusk”), if(ToD[2] == “Weekend”), if(ToD[3] == “Christmas”)…

Actually, I suppose you could split the string to create an array. I forget how to go about that in openHab, but something along the lines of ToD.split(",")

This is mostly right (it would be ToD.state.toString.split(",")) but it would be even easier to do:


Bit late to the party on this one. Lets just say im already getting ready for this year’s festivities.

I’ve taken work by @rlkoshak and the idea from @Steve40 and integrated them.

val logName = "Events"

rule "Calculate time of day state"
	System started or
	Channel 'astro:sun:local:civilDawn#event' triggered START or
	Channel 'astro:sun:local:daylight#event' triggered START or
	Channel 'astro:sun:local:civilDusk#event' triggered START or
	Channel 'astro:sun:local:civilDusk#event' triggered END or
	Time cron "0 0 12,0 * * ? *" // there is currently a bug where only one cron is triggered per rule so I've combined all three into one
	Thread::sleep(1000) // make sure we are a tad past midnight to give Astro a chance to recalculate DateTimes for today

	// Time of Day Calculations
	val long dawn_start = (vDawn_Time.state as DateTimeType).calendar.timeInMillis
	val long morning_start = (vDaylight_Time.state as DateTimeType).calendar.timeInMillis
	val long afternoon_start = now.withTimeAtStartOfDay.plusHours(12).millis
	val long dusk_start = (vDusk_Time.state as DateTimeType).calendar.timeInMillis
	val long night_start = (vNight_Time.state as DateTimeType).calendar.timeInMillis
	val long bed_start = now.withTimeAtStartOfDay.millis
	var curr = "UNKNOWN"
	switch now {
		case now.isAfter(dawn_start) && now.isBefore(morning_start):		curr = "DAWN"
		case now.isAfter(morning_start) && now.isBefore(afternoon_start):	curr = "MORNING"
		case now.isAfter(afternoon_start) && now.isBefore(dusk_start):		curr = "AFTERNOON"
		case now.isAfter(dusk_start) && now.isBefore(night_start):			curr = "DUSK"
		case now.isAfter(night_start):										curr = "NIGHT"
		case now.isAfter(bed_start) && now.isBefore(dawn_start):			curr = "BED"

	if(vTimeOfDay.state.toString != curr) {
		logInfo(logName, "Current time of day is now " + curr)
	// Time of Year Calculations
	val long xmas_dec_start = now.withDate(now.getYear(),12,1).withTime(0,0,0,0).millis		// 01/12 00:00
	val long xmas_dec_end = now.withDate(now.getYear(),12,31).withTime(23,59,59,999).millis	// 31/12 23:59
	val long xmas_jan_start = now.withDate(now.getYear(),1,1).withTime(0,0,0,0).millis		// 01/01 00:00
	val long xmas_jan_end = now.withDate(now.getYear(),1,6).withTime(0,0,0,0).millis		// 06/01 00:00
	curr = "UNKNOWN"
	switch now {
		case now.isAfter(xmas_jan_start) && now.isBefore(xmas_jan_end):		curr = "CHRISTMAS"
		case now.isAfter(xmas_dec_start) && now.isBefore(xmas_dec_end):		curr = "CHRISTMAS"
	if(vTimeOfYear.state.toString != curr) {
		logInfo(logName, "Current time of year is now " + curr)

This is currently showing as UNKNOWN for time of year. I’ve done it like this in case I want other times of year tracked. Although at the moment it’s only CHRISTMAS which I’m really interested in. It’s currently hiding the switches in my site map for the christmas lights. I will eventually write some rules which fire the light on automatically.

Idea being…

Outside lights ON if CHRISTMAS and DUSK and OFF at BED
Inside light ON if CHRISTMAS and someone is home (via presence detection) and only between certain hours and BED.

Thought I would share as i’ve take a lot from this community.


1 Like

Very nice. I’ve linked to this posting from the Time of Day design pattern.

For compelteness, the Astro 2 binding has a season channel which would be useful in expanding this.

1 Like

Thanks Rich,

It’s basically your work, so I’m taking no credit here. Feel free to link or even add into your post.

I’ll have a look at seasons. Cannot think of a good use at the moment but it’s good to know about all the same.