Moment Node (output formatted date/time

1,738 views
Skip to first unread message

Julian Knight

unread,
Jan 28, 2015, 4:34:31 AM1/28/15
to node...@googlegroups.com
Hi all,

As discussed in a previous thread, I was challanged to come up with a new node that would take either a Javascript date/time object or a string that can be resolved to such, apply a format and output.

Moment.JS is my usual tool for such jobs and so I've integrated it into a new node type: node-red-contrib-moment.

I'm posting this now to keep the pressure on myself to get things finished! It doesn't actually do much at present though you can certainly install it safely into your NR instance using:

    npm install https://github.com/TotallyInformation/node-red-contrib-moment/tarball/master

I've put in the basic UI, next I need to make the code do the right stuff! Currently, it just sends the input to debug.

Regards, J.

Nicholas O'Leary

unread,
Jan 28, 2015, 4:37:43 AM1/28/15
to node...@googlegroups.com
Hi Julian,

I see this fitting in with our other parser nodes - XML,JSON etc. By which I mean, it would be good if this could go either from String representation of a date to Date object, or Date object to a String representation. Unlike the XML/JSON nodes which only operate on msg.payload, I think it would be reasonable for the user to be able to pick which property of the message it should get applied to (defaulting to msg.payload).

Nick



--
http://nodered.org
---
You received this message because you are subscribed to the Google Groups "Node-RED" group.
To unsubscribe from this group and stop receiving emails from it, send an email to node-red+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Julian Knight

unread,
Jan 28, 2015, 3:49:13 PM1/28/15
to node...@googlegroups.com
Got it Nick. I'd only thought about going from string/object to string, I'll see if I can stretch the grey matter to output an object  as an option too. Good thinking.

I've already got the fields for choosing both input and output properties with defaults set to msg.payload.

Nice and easy to work with this stuff too, kudos to whoever dreamt this stuff up.

Regards. J.

Nicholas O'Leary

unread,
Jan 28, 2015, 3:56:11 PM1/28/15
to node...@googlegroups.com
Julian,

a couple comments on what you've described based on the approach we'd take if this were a core node... you are of course free to make your own design decisions :)

When I say to would be good to go either from String to Date or Date to String, I don't mean that would be an option of the node; it would just Do The Right Thing based on the type of the property it receives.

Typically, we would convert the property in place - not provide options for both input and output property names. If the user needs to preserve the original, they can stick a change node in front to take a copy of the property before hand.

N

Julian Knight

unread,
Jan 28, 2015, 4:31:13 PM1/28/15
to node...@googlegroups.com
High praise indeed, thanks Nick! Let's see where we end up.

In terms of the string/object stuff, I'll have a think about the options. I'd always assumed that the input could be either and the code would sort it transparently. For the output though, it would be much easier for users surely to have a simple tick box to choose whether the output is string or object? I suppose though that object->object is not sensible unless the node also allows for some time calculations! :) which had been at the back of my mind.

I'm not really inclined to force people to have to put a change node in just to switch from str->object or whatever, seems over complex to me. Worse, people would need to know the JS function to do the job which seems to negate one of the key selling points of NR?


So, also, what do you think about date/time calcs? Surely a common requirement as well? Better as a different, related, node or as options in the one node (probably with a check box to hide the details by default to keep it simple for people)?

One final question about what category to put nodes in. If you've loaded my test, you'll see I put it into a different category, "formats". The other time nodes are in function but this is already getting rather long - what do you think?

Nicholas O'Leary

unread,
Jan 28, 2015, 4:47:25 PM1/28/15
to node...@googlegroups.com
I think we've got a couple wires crossed here.

I'm not suggesting a change node is needed to switch from str->object. That part of my comment was based on your statement that you had "got the fields for choosing both input and output properties with defaults set to msg.payload." I was advocating only having to specify the name of the property of the message you want to format, and that the formatted version of the property should overwrite the original property. If the user wants to preserve the unformatted version, they can copy it sideways with a Change node.

I think we're agreed the node should just work, but to spell it out...

 - if the identified property is of type String, attempt to parse it using the provided format and convert it to a JavaScript Date object.
 - if the property is a JavaScript Data object, format it to a String

Are there other mappings you think the node should be able to handle? Whether they can be unambiguously identified without the user haven't to provide a hint is another matter.

I think a 'formats' category makes sense - and we should move the XML/JSON etc nodes over to that.

What sort of date/time calcs did you have in mind? You say they must be a common requirement, but I don't think anyone has asked for anything like that... so as ever, there's lots we could do, some of it we can be proactive about, but ultimately we have to prioritise what we spend our time and effort on based on feedback, suggestions and other requirements.

Nick

Julian Knight

unread,
Jan 29, 2015, 2:14:16 AM1/29/15
to node...@googlegroups.com
Ah, OK. my wrong.

Well, I'd already put separate input and output fields so I'll probably leave it as is. It is pretty clear to users and is only 1 extra configuration input so not complex.

I uploaded a new version (v0.2.0) last night that now works just fine. In the end, the way Moment.JS works dictated some of the input/format choices. I didn't manage to get the str->obj/obj->str processing working though as I couldn't think of a way to do it. However, the answer came to me this morning so I'll change it, hopefully today & publish a v1 to NPM.

----

Thinking about whether this should be in core or not, I'm leaning towards not at present. You seem to have got along without it quite happily so far and I think it would be best for the community as a whole to keep core as small as possible.

I've actually been thinking about how you install NR. The current method seems rather clunky to me. Would it not be better to always install via NPM but have an install script that runs (written in Node.JS of course so it is cross-platform) on installation that checks for a server.js file in the installation root. If one exists then just create a redserver-template.js or something like that. If it doesn't exist, just create it. That way it would be a lot easier to install with only one way of doing it regardless of whether you were embedding it or not AND you can leave npm to do the donkey work of doing updates.

The other advantage to that approach is that you can move ALL of your core nodes to their own npm packages with the core ones included as standard in the package.json. Again, this is much easier for newcomers to work out what is happening and where things are. And you get the added benefit of being able to easily maintain the nodes separately to the main code. You can also include contrib nodes in the core delivery if you want to.

Sounds like some big wins there all for the effort of writing a single install script.

-----

On the question of what processing I'd add to the moment node. I'm really surprised nobody has asked for date/time calculations like return a date 5 days from now or a time 3 hours ago. I hate doing these in JS as they tend to be fiddly and yet they are very common UI questions. I particularly want to be able, in my home automation scenario, Turn on a light in 1 hour and turn it off again 4 hours later. I might go to extremes and say something like "turn on light1 20 minutes after sunset"! Date based calculations might be less common in the HA situation but will be very common in others.

So the UI would be to add a couple of new input fields, a number and a selection list "Seconds", "Minutes", "Hours", "Days", "Weeks", "Months", "Years". Maybe even "Week Days" and "Weekend Days". This is similar to the Trigger node "then wait" part but more comprehensive since you would want date as well as time calcs and negative inputs not just positive ones (obviously negative Trigger offsets wouldn't be sensible).

The advantage of this is that it takes out a whole bunch of JS coding if anyone ever does need a date/time offset.

----

So here is a summary of things I'd like to do with the moment node (not necessarily immediately):
  • Make the default output more intelligent (obj->str/str->obj) - due today
  • Publish to NPM v1.0.0 - due today
  • Add a combo box to the Format field with common formats pre-populated
  • Improve the error messages when Moment.JS fails to interpret the input (say why)
  • Allow more input date/time formats - turns out Moment.JS doesn't really help here. At present, I see too many input failures from US/UK date formats, etc.
    It would be great if I could parse "human" inputs like "tomorrow" and "2 minutes from now". We can output them now but not input them.
  • Add date/time offset calculations

Dave C-J

unread,
Jan 29, 2015, 3:36:55 AM1/29/15
to node...@googlegroups.com
You're diverting your own thread now... :-)
Node-RED can already be installed via npm - that is how we install it on Bluemix (http://bluemix.net). 
The npm install step in the install will drag in any dependancies we put in package.json - so we can add any "external" but core nodes there if we need to.
You can also embed it in another app if you require - http://nodered.org/docs/embedding.html
But you only get the point releases that way and a lot of you guys always want the latest fixes etc ;-)

Re those HA examples you give - we already have Delay and Trigger nodes and a Suncalc node - so all those scenarios can be built with those. The node people have talked about needing is a full on Timer scheduler - the one in the inject node is only based on cron so is fairly limited.

Julian Knight

unread,
Jan 29, 2015, 4:54:06 AM1/29/15
to node...@googlegroups.com
OK, I think you got me twice over now!! Too many late-night sessions.

I'm sure you are right & I'm trying to be too clever by half. I'll drop the calculation idea.

And I need to do a clean install I think from npm. While I do like having the latest, I don't really have time right now to download/unpack etc. Even if I npm install from git each time, at least that is only one step to remember & all dependencies managed for me. Now I just need a script to automatically back up the config when NR starts.

Now I just need to find some time to actually USE it!


Julian Knight

unread,
Jan 29, 2015, 4:46:55 PM1/29/15
to node...@googlegroups.com
Darghhhh!!

When triggering a default Inject node, it claims that it will output a Date object - well to be fair, it IMPLIES it - if you happen to be a numpty pseudo programmer like me!!

Actually it DOESN'T, it outputs a NUMBER:

   node.warn(Object.prototype.toString.call(inp));

returns:
    [object Number]

So the processing for obj->str/str->obj doesn't work :(

Nicholas O'Leary

unread,
Jan 29, 2015, 4:51:44 PM1/29/15
to node...@googlegroups.com
A number is a distinct type from obj and string. So it could handle that as a third case. As to whether it emits a Date object, or a formatted string in that case could be an option, or default to Date.
N

--

Julian Knight

unread,
Jan 29, 2015, 5:39:35 PM1/29/15
to node...@googlegroups.com
Yeah, I fixed it but it was annoying. I was expecting a Date darn it :)

Anyway, it's done!! Published to Github and to NPM as v1, my very first NPM publications - hurrah!

https://www.npmjs.com/package/node-red-contrib-moment

In the end, I decided to make it handle null/missing inputs and simply output the current date/time as I thought this might be useful since you can now trigger it any old how without actually passing in a date & still get out a valid, formatted date. Documentation updated to make this clear.

Thanks for all the help. Bit of a steep learning curve.
Reply all
Reply to author
Forward
0 new messages