how to create string output from portions of JSON field

550 views
Skip to first unread message

An Yu

unread,
Jul 21, 2016, 2:14:57 PM7/21/16
to Node-RED
Hello,
I'm using this function to create human-readable date and time json variable.  Below is the code and output.

{"month":7,"day":21,"year":2016,"hours":11,"mins":6,"msecs":73}


I'm able to "stringify" the entire json string.  But what I really want is a string that looks like this:

2016/7/21, 11:6:73, 99
 
I heaven't been able to figured out how to do these things:
1)  How do I concatenate different parts of the JSON date object with commas and create a string object out of it?
2)  The last value in the string "99" is going to be an MQTT payload.  How do I concatenate the time stamp string with this value.
3)  How do I create a windows carriage return?

I'm trying to make comma delineated strings for easy spread sheet usage.  


My json timestamp object:

if ( !msg.timestamp ) msg.timestamp = Math.round(+new Date());


var dt = new Date(msg.timestamp);
var jsondate = {
 
'month': dt.getMonth() + 1,
 
'day': dt.getDate(),
 
'year': dt.getFullYear(),
 
'hours': dt.getHours(),
 
'mins': dt.getMinutes(),
 
'msecs': dt.getMilliseconds()
}
var s=JSON.stringify(jsondate);
msg
.payload=s;
return msg;

Julian Knight

unread,
Jul 21, 2016, 3:58:34 PM7/21/16
to Node-RED
Hi An,

JavaScript is rather lacking in date/time formatting natively I'm afraid. That's one of the reasons I recently updated my node-red-contrib-moment node. This now enables you to format things how you like.

In your case, you can simply pass the JavaScript timestamp into the moment node on msg.payload, specify the output format you want, tweak any locale/timezone settings is you need to and you will get what you want on the output msg.payload.

Hope that helps.

Regards, Julian.

Bobo

unread,
Jun 15, 2017, 6:50:58 AM6/15/17
to Node-RED
Unfortunately I have been trying to find what this actually looks like in the inject node, but no luck. Passing the timestamp in the inject node that your moment node would recognise looks like what exactly (in terms of format)?

Cheers

steve rickus

unread,
Jun 15, 2017, 9:31:01 AM6/15/17
to Node-RED
Bobo, the "format" of a timestamp is a large number...

If you wire an inject node (with the default output "timestamp") to a debug node, deploy it, and press the inject button, you will see a large integer that represents the number of milliseconds that have elapsed since the epoch -- this is the internal format for javascript dates. You can get the same results in plain js code by doing something like this:

var now = Date.now();
console
.log(now); // outputs 1497532579275

var then = Date.parse("2017-07-04 12:34:56");
console
.log(then); // outputs 1499186096000

var check = new Date(1497532579275);
console
.log(check.toISOString()); // outputs "2017-06-15T13:16:19.275Z"

W3 Schools has some nice online docs to understand javascript dates and how to manipulate them -- but Julian is correct that there are much better libraries (like moment) to help format them into human readable strings, convert between time zones, and to perform date arithmetic.
--
Steve

Bobo

unread,
Jun 15, 2017, 10:18:44 AM6/15/17
to Node-RED
Thanks Steve, but I guess I was being rather ambiguous with my question.

Regarding the moment node, when I send a blank string (using inject node) to the moment node I get a syntax error "The input property was NOT a recognisable date. Output will be a blank string"

So clearly I am doing something wrong with the input. Does someone have a trivial example flow of inject--> moment --> debug that takes as input the current date/time?

Cheers

steve rickus

unread,
Jun 15, 2017, 10:19:04 AM6/15/17
to Node-RED
An Yu,

There are many possible approaches that you could use -- but, if all you need is a function node that takes in a msg.timestamp and msg.payload and outputs a csv string, I would do something like this (untested):

var ts = msg.timestamp || Date.now(); // use the incoming timestamp, or the current timestamp
var arr = new Date(ts).toISOString().split(/[T.]/); // returns an array of [date, time, millis]

arr
[2] = msg.payload || 0; // replace the third element with the payload value
msg
.payload = arr.join(","); // create a csv string from the array

return msg;

The js method you need is the Array.join(separator) function -- but please don't try to append any OS-specific line terminators to your data. It will just cause you headaches while trying to use the data in your flows.

Perhaps a cleaner way to do this same thing is to NOT join the array into a csv string, but just return the array as the msg.payload. Then, wire the output to a csv node, which will take the array from the payload and convert it into csv (and should also handle the line terminators for you). This allows anyone else looking at your flow to see what you intend to do with the data, without having to open your function and try to understand it.
--
Steve

steve rickus

unread,
Jun 15, 2017, 10:21:47 AM6/15/17
to Node-RED
Use the "timestamp" mode of the inject node, instead of a blank string -- that IS the current date/time in its native form...

Bobo

unread,
Jun 15, 2017, 10:37:00 AM6/15/17
to Node-RED
Obviously I am not understanding how the moment node is used, in terms of input to the moment node. I have read the info but my JS knowledge is weak at the moment.

So can someone give me a reasonably trivial example of using the moment node? I have searched the existing flows but can't find anything.

Cheers

Julian Knight

unread,
Jun 15, 2017, 12:50:20 PM6/15/17
to Node-RED
If you have the latest version installed, I fear it isn't working. Currently trying to find time to fix.

The format you want is something like: yyyy/M/D, H:m:s

[{"id":"4da1b789.462108","type":"inject","z":"9974253c.de8db8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":200,"y":360,"wires":[["a2aaa5ce.876568"]]},{"id":"2a8fcf74.2c667","type":"debug","z":"9974253c.de8db8","name":"","active":true,"console":"false","complete":"false","x":610,"y":360,"wires":[]},{"id":"a2aaa5ce.876568","type":"moment","z":"9974253c.de8db8","name":"","topic":"","input":"","inputType":"msg","inTz":"Europe/London","adjAmount":0,"adjType":"days","adjDir":"add","format":"yyyy/M/D, H:m:s","locale":"en_GB","output":"","outputType":"msg","outTz":"Europe/London","x":400,"y":360,"wires":[["2a8fcf74.2c667"]]}]

You can find the format codes here: http://momentjs.com/docs/#/displaying/

Once you have a string, you can merge the other string using a function node or a change node using the Change mode and a regular expression or possibly the set mode with a JSONata expression.

Bobo

unread,
Jun 16, 2017, 12:27:47 AM6/16/17
to Node-RED
Hi Julian

Yes, your fear is justified :-) I thought I was going crazy there for a while. Your example flow threw the same error msg as I was getting.

Thanks for the accompanying info.

Cheers

Julian Knight

unread,
Jun 16, 2017, 1:43:40 AM6/16/17
to Node-RED
It is fixed now so if you update, all should be well.

Bobo

unread,
Jun 16, 2017, 1:51:34 AM6/16/17
to Node-RED
Yes, all good, thanks.
Reply all
Reply to author
Forward
0 new messages