I am trying to display the 'Last Seen' Attribute made available by Zigbee2MQTT for every device.
On the Zigbee2MQTT configure screen it shows as, 'Last Seen seconds/minutes/hours ago, which is exactly what I want to display, but when I extract the msg.payload.last_seen attribute, it is in ISO format (YYY-MM-DDTHH:MM:SS.SSS format)
Does anyone know if I can extract the elapsed time information or if not, a function to convert it into elapsed time in seconds?
Thanks
Hi @SomersetSmartHome
You should be able todo something like this...
const lastSeen = new Date(msg.payload.last_seen);
const diff = Date.now() - lastSeen.getTime();
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(diff / 60000);
const hours = Math.floor(diff / 3600000);
const display = `Last Seen ${seconds}/${minutes}/${hours} ago`
I dont use Zigbee (or DB), so might be incorrect
Side Note : Drink Plenty of Water this weekend - Im already struggling 
This is the standard for JSON representations of dates and times. You can use the moment node or $moment JSONata function to convert to other formats. The moment node has a humanizer node that may be useful to you.
The zigbee last_seen attribute is exactly that, the last time the device was seen, or the time this msg was sent, not how long it has been since the last_seen time. Note: the zigbee2MQTT last_seen value is in milliseconds not ISO date format
You will have to save the last_seen value in context and then deduct the next last_seen to give the time between.
This works for me. Note that my MQTT topic input from zigbee2MQTT is formatted like : zigbee2mqtt/Smart Socket 04/mqttIn so that is how I got the deviceName
const [source, deviceName, transmission] = msg.topic.split('/')
const thisTimeSeen = msg.payload.last_seen
const lastTimeSeenData = context.get('lastSeen') ?? {}
const lastTimeSeen = lastTimeSeenData?.[deviceName] ?? 0
lastTimeSeenData[deviceName] = thisTimeSeen
context.set('lastSeen', lastTimeSeenData)
const timeSinceLastSeen = thisTimeSeen - lastTimeSeen
// In seconds
const elapseTimeSeconds = Math.floor(timeSinceLastSeen / 1000)
msg.payload = elapseTimeSeconds
msg.time = msToTime(timeSinceLastSeen)
return msg
/**
* Description Converts milliseconds to hours:minutes:seconds string in 'locale' format.
* Create a Date object with the number of milliseconds, rounding the number to the nearest second
* Convert Date to time string using UTC as the time zone to avoid daylight saving errors (or time zone offset)
*
* @param {number} milliSeconds - Number of milliseconds to convert. Usually as a response to Date.now() or Date.getTime()
*
* @returns {string} - Time string. In UK "hh:mm:ss"
*/
function msToTime(milliSeconds) {
const date = new Date(milliSeconds)
return date.toLocaleTimeString('en-GB', { timeZone: 'UTC' })
}
I have also included a function to get the time
It is in ISO8601 format. When received into Node-RED by an mqtt-in node, you can perhaps have it auto-translate to milliseconds since UNIX epoch automatically (the JSON parsed setting I think).
This from MQTT Explorer:

With the right settings in Zigbee2MQTT, you can also have the data broken out. So listening to the topic: zigbee2mqtt/<device_name>/last_seen gives you the answer directly instead of having to wade through the JSON yourself.
Not what the OP asked for. You can take the last seen date/time and pass it through the humaniser node to get the answer asked for. Or you can do the calculation manually using the milliseconds amount of course.
He was asking for the elapsed time which is not what last_seen represents
I apologise for the assumption on last_seen format, I have looked it up again and it can be configured
### [last_seen](https://www.zigbee2mqtt.io/guide/configuration/all-settings.html#last-seen)
Add a last_seen attribute to MQTT messages, contains date/time of last Zigbee message
advanced:
last_seen: 'disable'
* Type: `string`
* Default: `"disable"`
* Possible values: `disable`, `ISO_8601`, `ISO_8601_local`, `epoch`
It would also appear that an elapsed time can be added
### [elapsed](https://www.zigbee2mqtt.io/guide/configuration/all-settings.html#elapsed)
elapsed
Add an elapsed attribute to MQTT messages, contains milliseconds since the previous msg
advanced:
elapsed: false
Type: boolean
Default: false
I found these in All settings | Zigbee2MQTT
So you learn something new every day
And I just spotted that as well. 
Thanks for all the replies.
I have to admit they are pretty much all above my pay grade - basically I didn't understand the answers!
I found node-red-contrib-nostalgic. A node to tell you how long ago it received a message.
This seems to do what I want.
I have installed node-red-contrib-moment and will play around with that because my next task is to add a datalogger, so timestamps will be crucial there.
Thanks again
The main moment node will convert from and to any date/time format that the MomentJS library can make sense of. It also handles timezone and daylight savings.
The recommended approach to these things is to always store dates and times in UTC and only convert to local when getting user input or displaying output.