This should work, I’m fairly new at this though. So set the date to the last time your shift changes. Inject it it will add 4 weeks and store the value.
The second inject will send a time stamp that will be compared to the date stored. If the timestamp injected is > the stored date it will output on
through msg.date_time_now. Then it will send a timestamp that will have 4 weeks added to it, starting the cycle over.
You need to enable context storage to ensure that the date is saved through restarts and updates.
[{"id":"b8e1cab0.ea723","type":"inject","z":"7d105d71.cc18e4","name":"Set daily check time","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":370,"y":3220,"wires":[["e068dee8.1969c"]]},{"id":"e068dee8.1969c","type":"function","z":"7d105d71.cc18e4","name":"date checker","func":"var date_time = context.get(\"future_date\"); //change \"future_date\" for each instance\n\nif(msg.topic == \"set\") {\n date_time = msg.payload;\n} else if (msg.payload >= date_time) {\n date_time_now = \"on\";\n} else {\n date_time_now = \"off\";\n}\ncontext.set(\"future_date\", date_time); //change \"future_date\" for each instance\nnode.status({ text: date_time_now });\n\nmsg.date_time_now = date_time_now; \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":995,"y":3220,"wires":[["e001e920.a9d21"]],"icon":"node-red-dashboard/ui_dropdown.png","l":false},{"id":"1080caa7.f9f055","type":"inject","z":"7d105d71.cc18e4","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"*/1 0 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"2021-04-16","payloadType":"str","x":170,"y":3060,"wires":[["5813a7c1.38ccc8"]]},{"id":"ff5bba43.29bf78","type":"change","z":"7d105d71.cc18e4","name":"set timestamp","rules":[{"t":"set","p":"topic","pt":"msg","to":"set","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":840,"y":3180,"wires":[["e068dee8.1969c"]]},{"id":"5813a7c1.38ccc8","type":"function","z":"7d105d71.cc18e4","name":"Convert to timestamp","func":"p = msg.payload;\nmsg.payload= Date.parse(p);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":3060,"wires":[["de35e328.267e2"]]},{"id":"796f3459.f435ac","type":"debug","z":"7d105d71.cc18e4","name":"\"on\", sent once every 4 weeks","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1290,"y":3060,"wires":[]},{"id":"de35e328.267e2","type":"moment","z":"7d105d71.cc18e4","name":"","topic":"","input":"payload","inputType":"msg","inTz":"America/New_York","adjAmount":"04","adjType":"weeks","adjDir":"add","format":"x","locale":"C","output":"payload","outputType":"msg","outTz":"America/New_York","x":760,"y":3060,"wires":[["ff5bba43.29bf78"]]},{"id":"e001e920.a9d21","type":"switch","z":"7d105d71.cc18e4","name":"","property":"date_time_now","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"},{"t":"eq","v":"off","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":1170,"y":3220,"wires":[["de35e328.267e2","796f3459.f435ac"],[]]},{"id":"7ba58f52.e395f","type":"comment","z":"7d105d71.cc18e4","name":"set start date of most recent shift change, keep the same format.","info":"","x":290,"y":2980,"wires":[]}]
https://nodered.org/docs/user-guide/context#saving-context-data-to-the-file-system