Holiday Selection Script

I am not very good with Javascript. I found the Easter function and Googled how to setup the rest. This script is in a function node that I use for my holiday lights. It used to work but now that I have changed some things, it doesn't. I found a script from Stack Overflow that figures out when the non-fixed date holidays are that I would like to implement but I would like to have a working base while I try to figure out.

A 0 or 1 is sent into the function node as the payload. Any help is greatly appreciated.

``````const d = new Date();
var day = d.getDay();
var year = d.getFullYear();

function Easter(Y) {
var C = Math.floor(Y/100);
var N = Y - 19*Math.floor(Y/19);
var K = Math.floor((C - 17)/25);
var I = C - Math.floor(C/4) - Math.floor((C - K)/3) + 19*N + 15;
I = I - 30*Math.floor((I/30));
I = I - Math.floor(I/28)*(1 - Math.floor(I/28)*Math.floor(29/(I + 1))*Math.floor((21 - N)/11));
var J = Y + Math.floor(Y/4) + I + 2 - C + Math.floor(C/4);
J = J - 7*Math.floor(J/7);
var L = I - J;
var M = 3 + Math.floor((L + 40)/44);
var D = L + 28 - 31*Math.floor(M/4);

return D
}

switch (d.getMonth() + 1) {
case 2:  // Valentine's Day
if (day >= 7 && day <= 14) {
return newMsg;
}
break;
case 3:  // St. Patrick's Day
if (day >= 15 && day <= 17) {
return newMsg;
}
break;
case 4: // Easter
var E = Easter(year);
if (day >= E - 2 && day <= E) {
return newMsg;
}
break;
case 5: // Memorial Day
if (day >= 23 && day <= 25) {
return newMsg;
}
break;
case 7: // 4th of July
if (day >= 1 && day <= 4) {
return newMsg;
}
break;
case 10: // Halloween
if (day >= 1 && day <= 31) {
return newMsg;
}
break;
case 11: // Thanksgiving
if (day >= 15 && day <= 17) {
return newMsg;
}
break;
case 12: // Christmas
if (day >= 1 && day <= 31) {
return newMsg;
}
break;
default:
return newMsg;
}
``````

That script returns newMsg if today is one of your chosen holiday periods?
eg If it's November 15th, 16th or 17th it returns output:7 etc

Otherwise it doesn't return anything.

It seems to work for me today (November 5th, Bonfire Night! ) if define thanksgiving as day >=1 && day <=17

What problem do you see?

Thank you for the response jbudd. Yes, the script is supposed to look at today's date and then match the month. If there is a match and the date range matches, then it should send newMsg with the payload of 0 or 1 and the corresponding output and select. If there is no matches, then it should fall to the default.

It was working properly before but then I added the default and changed the return newMsg. Nothing that I would think would prevent it from working. The response I get now is nothing. I put an inject node with a payload of 0 or 1 going into this function node. Then I put a debug node on the output. I get nothing in the debug node. One time I set the month as 2 and it worked then when I made it use the default it didn't. I then changed something and now I'm back to nothing in the debug node.

try

``````const d = new Date();
//const d = new Date(2022,3,17); // easter 2022
var day = d.getDay(); // 0-6
var year = d.getFullYear();
var date =d.getDate(); //1-31
var month = d.getMonth() + 1;

function Easter(Y) {
var C = Math.floor(Y/100);
var N = Y - 19*Math.floor(Y/19);
var K = Math.floor((C - 17)/25);
var I = C - Math.floor(C/4) - Math.floor((C - K)/3) + 19*N + 15;
I = I - 30*Math.floor((I/30));
I = I - Math.floor(I/28)*(1 - Math.floor(I/28)*Math.floor(29/(I + 1))*Math.floor((21 - N)/11));
var J = Y + Math.floor(Y/4) + I + 2 - C + Math.floor(C/4);
J = J - 7*Math.floor(J/7);
var L = I - J;
var M = 3 + Math.floor((L + 40)/44);
var D = L + 28 - 31*Math.floor(M/4);

return D
}

switch (month) {
case 2:  // Valentine's Day
if (date >= 7 && date <= 14) {
msg = { payload: 1,output:1,select:1 };
}
break;
case 3:  // St. Patrick's Day
if (date >= 15 && date <= 17) {
msg = { payload: 1,output:2,select:1 };
}
break;
case 4: // Easter
var E = Easter(year);
if (date >= E - 2 && date <= E) {
msg = { payload: 1,output:3,select:1 };
}
break;
case 5: // Memorial Day
if (date >= 23 && date <= 25) {
msg = { payload: 1,output:4,select:1 };
}
break;
case 7: // 4th of July
if (date >= 1 && date <= 4) {
msg = { payload: 1,output:5,select:1 };
}
break;
case 10: // Halloween
if (date >= 1 && date <= 31) {
msg = { payload: 1,output:6,select:1 };
}
break;
case 11: // Thanksgiving
if (date >= 15 && date <= 17) {
msg = { payload: 1,output:7,select:1 };
}
break;
case 12: // Christmas
if (date >= 1 && date <= 31) {
msg = { payload: 1,output:8,select:1 };
}
break;
default:
msg = { payload: 0,output:9,select:1 };
}
return msg
``````

as day is 0-6 and date is 1-31

I changed the start date for the Thankgiving section:

``````    case 11: // Thanksgiving
if (day >= 1 && day <= 17) {
return newMsg;
}
break;
``````

And it seems to work

If a `switch` condition is met but the `if` in the condition is not met, you just do a return so no message is returned.
I would move the `return newMsg` out of all the `case` code and move it to the bottom the flow outside the `switch` block. And I would initially have as `let newMsg = {payload: "nothing matches"}` (or what ever you want) as the first line of the function.

This way you set a default msg if nothing matches.

Thank you everyone for all of the feedback. I found out that the issue when nothing matches. @zenofmud You mention putting `let newMsg = {payload: "nothing matches"}` at the beginning. I have a "default" at the bottom of the switch. I thought the default was for when nothing matched and that it didn't matter where it was placed? Thank you for letting me know about moving the `return newMsg`. I didn't know that would work.

Edit:
Ok, I did what you said and placed `let newMsg = { payload: msg.payload,output:9,select:1 };` at the top below the year variable. Then I removed the "default" from the switch. It works perfectly now. I still don't understand why the "default" didn't work. Thanks again.

@Amishman the switch code is doing what you told it to do. For any of the months (2,3,4,5,7,10,11,12) you have `case` statements for, it will run that batch of code. for the other months (1,6,8,9) it will run the code in the `default` code.

However, not all `case` code will retunn a msg. For example look at July:

``````    case 7: // 4th of July
if (day >= 1 && day <= 4) {
return newMsg;
}
break;
``````

If the day is not 1, 2, 3, or 4 you break from the `case` code and drop to the botton and nothing is returned.

You should leave the default in even if you just have a `break` there.

In your original code you coudl test by changing the switch to look at msg.payload like this:

``````//switch (d.getMonth() + 1) {
``````

Then send in a `1` and it will output the error msg.
Send in a `2` and it will output a msg since you are checking if today is between `7` and `14`.
Send in a `3` and you will get no output because the `case 3:` code has an `if` that tests if the day is between `15` and `17` and since today is the `7th` the `if` condition is not met and tehn yo `break` out of the `switch` and since there is nothing else there, no messge is returned.

So you see, your code was working perfectly the way you `told` it to, just not how you `wanted` it to. (computers are noterious for this )

I hope this helps you to understand what was happening.

Just to reiterate, `day` outputs 0-6 sunday to saturday.
so

`````` case 3:  // St. Patrick's Day
if (day >= 15 && day <= 17)
``````

The if statement will always be false, as `day` is never above 6.
In my code above i have use `date`, which outputs 1 - 31.

1 Like

@zenofmud Thank you for the explanation. I thought if it did not match both the case and if statement that it would send the newMsg in the default.

@E1cid Thank you for catching that. I completely missed that in your first post. I have corrected it in my script now.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.