Combine transformations in item definition

This topic is more or less used as click bait for this topic:

What I need to achieve is to parse an MQTT message with JSONPATH and convert the result from a number to a DateTime in one go. The specific value can be obtained through JSONPATH as a number (actually an Epoch Time) but this cannot be placed in a DateTime type item (i think at least need to be multiplied by 1000 for seconds to millis). I was thinking of combining 2 transformations at once, but have not been able to find any related forum topic through a search. Hope to find a generic solution by (cross) posting this. So:

What is the proper syntax to combine two transformations in one item definition that is bound to an MQTT channel?

Current item:

Number   Presence_RobertPhone_Timestamp "Timestamp [%d]"    <clock>    (Presence_RobertPhone) {mqtt="<[ext:owntracks/robert/iphone:state:JSONPATH($.tst)]"}

Required item:

DateTime   Presence_RobertPhone_Timestamp "Timestamp [%d]"    <clock>    (Presence_RobertPhone) {mqtt="<[ext:owntracks/robert/iphone:state:<DOUBLE TRANSFORMATION HERE>]"}

cc @rlkoshak

When I hit a situation like this, I fall into JavaScript, with something like

DateTime   Presence_RobertPhone_Timestamp "Timestamp [%1$tm/%1$td %1$tH:%1$tM]"    <clock>    (Presence_RobertPhone) {mqtt="<[ext:owntracks/robert/iphone:state:JS(owntime.js)]"}

transform/owntime.js (untested):

(function(json){
var otdata = JSON.parse(json);
return new Date(otdata.tst * 1000).toISOString();
})(input)
3 Likes

You are my hero. :slight_smile:

That works flawlessly. You had one typo: otdat.tst should have been otdata.tst.

1 Like

Looks like your JS in some way does not repect time zones. The timestamp is 1 hour behind local time (I live in the Netherlands, CET). Do you have a quick fix?

JavaScript’s Date.toISOString() always returns the date object in UTC timezone (hence the “Z” at the end). It seems like you would have to jump through some hoops to get the Date object to be rendered as a string in the local timezone. I’ve adapted a snippet from StackExchange to maybe get the job done:

(function(json){
var otdata = JSON.parse(json);
var tzoffset = new Date().getTimezoneOffset() * 60000;
return new Date((otdata.tst * 1000) - tzoffset).toISOString().slice(0,-1);
})(input)

Thanks again.

You actually don’t need the slice. My working example is:

owntime.js

(function(json){
	var otdata = JSON.parse(json);
	var tzoffset = new Date().getTimezoneOffset() * 60000;
	return new Date(otdata.tst * 1000 - tzoffset).toISOString();
})(input)
1 Like

This might be resulting in an incorrect DateTimeType (off by the hour difference between London and Amsterdam), but formatting to look as if it’s correct. This isn’t to say that leaving the “Z” on the end isn’t any worse than the alternatives. A detailed re-visit of timezone handling in DateTimeType and how it’s formatted is something to think about. In any case, glad it’s working for you!