Date object in a function node not created

I got a function node which collects MQTT Status messages from my zigbee2mqtt Broker. In particular I want the last_seen time stamp to monitor my zigbee network.
when a new device is detected an array is extended like:

dlist.push({ 
        name: device, 
        status: msg.payload.state, 
        time: new Date(msg.payload.last_seen), 
        ignored: false, 
        alarm: false })

The problem is the dlist.time value. Despite that its constructed as a date object it is inserted as a date/time string like 2025-11-09T09:46:02.000Z

msg.payload.last_seen is a date string but I want a date object in the table. Why is this conversion not working?

if msg.payload.last_seen really is a string containing exactly 2025-11-09T09:46:02.000Z then there is no reason that wouldn't work

Proof in Node REPL:

So something is not quite right. either the path is wrong or its not actually a string or...

Add the below to your function:

const theType = typeof msg.payload.last_seen
const theValue = msg.payload.last_seen
node.warn({theType, theValue})
dlist.push({ 
        name: device, 
        status: msg.payload.state, 
        time: new Date(msg.payload.last_seen), 
        ignored: false, 
        alarm: false })

and show us what you see in debug pnael.

Forgot to mention, dlist.time will not get you your array element value (pretty sure thats just a typo tho)

as expected:

{ theType: "string", theValue: "2025-11-09T11:14:01+01:00" }

This is really odd. When I create a simple test script outside NR it works fine. the array is stored at the end in a global variable:

global.set("devices", dlist)

So are you really trying to get the value via dlist.time?

No for sure. dlist is an array. I don't evaluated that.

When I construct my device table from scratch I have another function to initialise only my zigbee coordinator like


var d = [{
    name:"Coordinator",
    status: "online",
    time: Date.now(),
    ignored: false,
    alarm: false
}];
global.set("devices",d)

This works as expected. the d.time is a date object. All other devices added with the function above are not.

The DateConstructor has 3 overloads. Could that be a reason?

d is an array. it will never be able to reveal the value of an inner element. d[0].time will.

No. they are there to provide different means of instantiating the date object (by string, by number, by other date object)

Ok I think I identified the issue:

The javascript date constructor might work fine however in NR it is always(!) displayed and also exported as a string. You need to represent your date object as number of millisecond since 1970 thus:

time: Date.parse(msg.payload.last_seen)

This value can be inspected in the NR debug- and context data windows. And of course it allows date sorting functions to be added.

You need to read up a bit on how JavaScript objects are stringified. When a data object is sent to the debug panel or indeed to MQTT, it is automatically converted by JavaScript to an ISO8601 string which is always shown as Zulu time (AKA GMT, AKA UTC).

This is because the communication between JavaScript and HTML (the panel) or MQTT uses JSON, not JavaScript Objects. JSON does not support anything other than JavaScript primitives (number, string, boolean, etc).

"stringified" : nice word for the problem :wink:
I understand this needed for display, JSON export etc. But what about the internal NR variables in flows or global: do the store a date object or also only the stringified version?

It can get a little complex but in general, when using the default memory based context variables, there is no need for them to be stringified. However, file-based context and possibly others do have to be converted, these are physical limitations not Node-RED ones.

Anywhere that your data has to leave the node.js environment will generally result in a conversion of some sort. This is true for databases as well though they have richer data types to work with, including their own timestamps. So it is less obvious there.