Moment Node: using a flow or global variable for the adjustment value

I have been struggling for weeks on this issue so have finally decided to reach out for help with the Moment Node.

I am currently configuring reticulation station start times in NodeRed. I have a function node feeding into a moment node. I then have a number of other moment nodes coming off the output of the first moment node. The reason for this is that the first moment node is fed the initial start time from the function node and then this cascades all other retic station start times based off the original time. I like the moment node as it handles increasing start times that cross the 'hour' boundaries. Trying to handle all this within a function node was too cumbersome.

My problem is that i need the time adjustment amounts to be called from a flow variable or global variable but I dont know the correct syntax to enter into the adjustment dialogue box to make this happen. I can call (see image) an environmental variable using the $(env_name) syntax but this variable type doesn't suit my purpose as it cant be manipulated and re-set by a function node.

Any help on calling a flow variable within the moment node or altering the environmental variable value within the flow.....or another method??

Did you click on the msg box with the down arrow?
Screen Shot 2021-01-01 at 6.14.08 AM

Thanks: however the Input is used to receive the start time (output) from the previous node. The initial moment node receives this from the function node; however the subsequent moments receive their start time from the previous moment node with an adjustment added. The adjustment value does not come from the input. You can use an environment variable in the adjustment (i used $(test2) in my image) but I would like to call a flow variable or global variable

Example:
Function msg.payload = 05:00 ----> Session Start (moment 1)
Session Start (moment1) msg.payload = 05:00 + adjustment value(10) ---> Session Start 2 (moment2)
Session Start 2(moment2) msg.payload = 05:10 + adjustment value(10) --> Session Start 3 (moment3)
Session Start 3(moment3) msg.payload = 05:20 + adjustment value(10) --> Session Start 4 (moment4)

In the function node why not create each of the adjustments and store them in different flow variables? Then each moment node can get its value from the stored value.

if this doesn’t work please provide your flow because I’m not sure what you are doing

1 Like

Hi, you should really only use moment as the last node and for presentation purposes. Any adjustements and offsets should be made to the Date object (or timestamp) before passing into the moment node to present a nice format (even then the moment node isnt necessary).

e.g...
NhATAVyIHw

demo flow...

[{"id":"3a02a4d6.5a737c","type":"inject","z":"64ce1d00.d049e4","name":"now + global.minuteOffset","props":[{"p":"topic","vt":"str"},{"p":"payload"},{"p":"interval","v":"minute","vt":"str"},{"p":"number","v":"minuteOffset","vt":"global"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":190,"y":660,"wires":[["976589bf.3f3938"]]},{"id":"207eac78.4382c4","type":"inject","z":"64ce1d00.d049e4","name":"add 3 month","props":[{"p":"topic","vt":"str"},{"p":"payload"},{"p":"interval","v":"month","vt":"str"},{"p":"number","v":"3","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":700,"wires":[["976589bf.3f3938"]]},{"id":"474051ee.d167a","type":"debug","z":"64ce1d00.d049e4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":350,"y":740,"wires":[]},{"id":"9f98918d.8ac1b","type":"inject","z":"64ce1d00.d049e4","name":"add 1 year","props":[{"p":"topic","vt":"str"},{"p":"payload"},{"p":"interval","v":"year","vt":"str"},{"p":"number","v":"1","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":740,"wires":[["976589bf.3f3938"]]},{"id":"976589bf.3f3938","type":"function","z":"64ce1d00.d049e4","name":"dateAdd","func":"function dateAdd(date, interval, number) {\n    var origDate = new Date(date);\n    var ret = new Date(date); \n    var checkRollover = function () { if (ret.getDate() != origDate.getDate()) ret.setDate(0); };\n    switch (String(interval).toLowerCase()) {\n        case 'year': ret.setFullYear(ret.getFullYear() + number); checkRollover(); break;\n        case 'quarter': ret.setMonth(ret.getMonth() + 3 * number); checkRollover(); break;\n        case 'month': ret.setMonth(ret.getMonth() + number); checkRollover(); break;\n        case 'week': ret.setDate(ret.getDate() + 7 * number); break;\n        case 'day': ret.setDate(ret.getDate() + number); break;\n        case 'hour': ret.setTime(ret.getTime() + number * 3600000); break;\n        case 'minute': ret.setTime(ret.getTime() + number * 60000); break;\n        case 'second': ret.setTime(ret.getTime() + number * 1000); break;\n        default: ret = undefined; break;\n    }\n    return ret;\n}\nmsg.payload = dateAdd(msg.payload, msg.interval, msg.number)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":340,"y":700,"wires":[["474051ee.d167a"]]},{"id":"c74f5d14.80622","type":"inject","z":"64ce1d00.d049e4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":580,"wires":[["102592dc.7fca2d"]]},{"id":"102592dc.7fca2d","type":"change","z":"64ce1d00.d049e4","name":"set some globals","rules":[{"t":"set","p":"minuteOffset","pt":"global","to":"10","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":580,"wires":[[]]}]

e.g 2

[{"id":"3a02a4d6.5a737c","type":"inject","z":"64ce1d00.d049e4","name":"now + global.minuteOffset","props":[{"p":"topic","vt":"str"},{"p":"payload"},{"p":"interval","v":"minute","vt":"str"},{"p":"number","v":"minuteOffset","vt":"global"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":190,"y":660,"wires":[["72c1fdde.c18c94"]]},{"id":"474051ee.d167a","type":"debug","z":"64ce1d00.d049e4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":710,"y":720,"wires":[]},{"id":"c74f5d14.80622","type":"inject","z":"64ce1d00.d049e4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":620,"wires":[["102592dc.7fca2d"]]},{"id":"102592dc.7fca2d","type":"change","z":"64ce1d00.d049e4","name":"set global.minuteOffset to 15","rules":[{"t":"set","p":"minuteOffset","pt":"global","to":"15","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":620,"wires":[[]]},{"id":"72c1fdde.c18c94","type":"function","z":"64ce1d00.d049e4","name":"dateAdd","func":"function dateAdd(date, interval, number) {\n    var origDate = new Date(date);\n    var ret = new Date(date); \n    var checkRollover = function () { if (ret.getDate() != origDate.getDate()) ret.setDate(0); };\n    switch (String(interval).toLowerCase()) {\n        case 'year': ret.setFullYear(ret.getFullYear() + number); checkRollover(); break;\n        case 'quarter': ret.setMonth(ret.getMonth() + 3 * number); checkRollover(); break;\n        case 'month': ret.setMonth(ret.getMonth() + number); checkRollover(); break;\n        case 'week': ret.setDate(ret.getDate() + 7 * number); break;\n        case 'day': ret.setDate(ret.getDate() + number); break;\n        case 'hour': ret.setTime(ret.getTime() + number * 3600000); break;\n        case 'minute': ret.setTime(ret.getTime() + number * 60000); break;\n        case 'second': ret.setTime(ret.getTime() + number * 1000); break;\n        default: ret = undefined; break;\n    }\n    return ret;\n}\nmsg.payload = dateAdd(msg.payload, msg.interval, msg.number)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":400,"y":660,"wires":[["6c64b591.f2b0fc","2942f8d.1e5fb08"]]},{"id":"6c64b591.f2b0fc","type":"change","z":"64ce1d00.d049e4","name":"add 5 year","rules":[{"t":"set","p":"interval","pt":"msg","to":"year","tot":"str"},{"t":"set","p":"number","pt":"msg","to":"5","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":660,"wires":[["777b3bf8.a77da4"]]},{"id":"777b3bf8.a77da4","type":"function","z":"64ce1d00.d049e4","name":"dateAdd","func":"function dateAdd(date, interval, number) {\n    var origDate = new Date(date);\n    var ret = new Date(date); \n    var checkRollover = function () { if (ret.getDate() != origDate.getDate()) ret.setDate(0); };\n    switch (String(interval).toLowerCase()) {\n        case 'year': ret.setFullYear(ret.getFullYear() + number); checkRollover(); break;\n        case 'quarter': ret.setMonth(ret.getMonth() + 3 * number); checkRollover(); break;\n        case 'month': ret.setMonth(ret.getMonth() + number); checkRollover(); break;\n        case 'week': ret.setDate(ret.getDate() + 7 * number); break;\n        case 'day': ret.setDate(ret.getDate() + number); break;\n        case 'hour': ret.setTime(ret.getTime() + number * 3600000); break;\n        case 'minute': ret.setTime(ret.getTime() + number * 60000); break;\n        case 'second': ret.setTime(ret.getTime() + number * 1000); break;\n        default: ret = undefined; break;\n    }\n    return ret;\n}\nmsg.payload = dateAdd(msg.payload, msg.interval, msg.number)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":720,"y":660,"wires":[["474051ee.d167a"]]},{"id":"2942f8d.1e5fb08","type":"debug","z":"64ce1d00.d049e4","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":450,"y":720,"wires":[]}]
1 Like

I did look at trying to manipulate the timestamp in a function and then output the time - problem is that I have 8 Stations and when they all run one after another it takes me past an hour and I struggled to handle this in the function. There is also the added complexity that I have a switch at the start of my flow for Scheduled Start vs Manual start. Scheduled is as below but the manual takes the current time

eg:
Station 1 start - 5:00am
Station 2 start - 5:10am
Station 3 start - 5:20am
Station 4 start - 5:30am
Station 5 start - 5:40am
Station 6 start - 5:50am
Station 7 start - 6:00am
Station 8 start - 6:10am

Thank you - apologies....I didnt know how to take your source code and import it into my node-red to see the configuration of the flow. Googled it and now can see your function and how it handles the time manipulation. I will do as you suggested and use this instead of multiple instances of the moment node

Really appreciate the assistance.

Sorry to ask another question but using your above example how do i inject the initial start time of say 5:00am. The example above inputs the current time but I cant seem to find a way to alter this so that it starts at a set time into the future.

If you look at the inject node, you can set it to inject at specific times and day(s)
there are also some 'cron' nodes you could use.

Tbh, as @zenofmud alludes to, you might be better off using a scheduling node.

I wrote node-red-contrib-cron-plus so obviously I'd recommend that one but more so because you can have any amount of schedules from one node. And it is 100% programmable.

1 Like

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