Help getting time difference between two dates from Home Assistant

I've read a bunch of the posts on the forum for the same question, but I still can't get it to work.

Here's my code in the function node:

var last = global.get("homeAssistant.states['device_tracker.iphone_13'].last_changed");
var now = new Date().getTime();
var diff = now - last;
msg.payload = diff;
return msg;

The formatting for the last changed is 2022-12-11T02:04:19.408425+00:00, which from what I read is something javascript can understand.

The error I'm getting is:

The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.(2363)

So it's not thinking last is the right format?

So I tried this:

var last = new Date('2022 - 12 - 11T02: 04: 19.408425 + 00: 00');
var now = new Date().getTime();
var diff = now - last;
msg.payload = diff;
return msg;

and I get the same message.

I've tried putting dates in various date formats copied from javascript tutorial directly in there and I keep getting the same error.

In tutorials I see random ; at the ends of lines, so I've tried different combinations of that too.

If I just put in a number instead of last in the formula, it works.

This must be something super simple but I can't figure it out. There are probably a million different silly errors I could have. Anyone able to help me please?

What is the expected output ?

try:

node.warn(`last=${last} now=${now}`)

and then see in the debug log whether they're both numbers of the approx same magnitude...

This works, so if your format from HA is the same as in your code example you would need to remove the white space.

let last = new Date('2022-12-11T02:04:19.408425+00:00').getTime();
let now = new Date().getTime();
let diff = now - last;
msg.payload = diff;
return msg;

You probably need last.getTime()

I suspect it is the fact that you have added getTime() to the last calculation.

And the fact that I removed the white space. Try it with white space, then you could confirm your suspicions.

You are right, that is why the second example posted did not work

But I think the problem with the original code may just be the missing getTime().

That's why i added getTime() and i mentioned white space just in case there was some in the HA global, as there was some confusion in the HA format.

I think the difference in the two times, most likely in milliseconds. Once I can get it to work I'll do a unit conversion.

Thanks @E1cid, @tve and @Colin.

So when I manually put in the date, it works with the getTime() at the end, as expected. (You were right, the white space ended up not mattering.) I understand now that the getTim() command/ function? converts a given date to the number of milliseconds since January 1, 1970, so that is why that is needed.

Now what still doesn't work is trying to do this same operation when pulling the date from global context.

Let me walk through it to see if the error presents itself. To find the path:

"homeAssistant.states['device_tracker.my_iphone_13'].last_changed"

I click on the Context Data tab. Then many times this is empty, so I hit refresh and then homeAssistant pops up.

Expanding this list a few times give me a huge list of states under states: object.
Screenshot 2022-12-11 at 5.10.09 AM

Then I need to find the one I want. Once I find it, I use the copy path button to grab the path.

Then I take this copied path, and put it into the code as shown below, but I first change the " to ' in the [] and then add " to the outside.
Original:
homeAssistant.states["device_tracker.my_iphone_13"].last_changed
Modified:
"homeAssistant.states['device_tracker.my_iphone_13'].last_changed"

Now the following code has no errors in the function node (unlike before, when I didn't have the getTime(), but when I inject a message, either a timestamp or just a string, I get the error below in the debug node:

var last = global.get("homeAssistant.states['device_tracker.my_iphone_13'].last_changed").getTime();
var now = new Date().getTime();
var diff =now-last;
msg.payload = diff
return msg;

TypeError: Cannot read properties of undefined (reading 'getTime')

So for some reason it's not pulling that data from context correctly? Is there some even simpler code I could test to see what it is pulling from context? I tried changing the msg.payload = last to see if it would spit out the time since epoch in milliseconds, but I got the same message.

Then I commented out the getTime() as well to see if I could have it just return the date, but undefined comes out of the debug node.

Question: why does the second line need the new operator but none of the others do? The undefined makes me think it doesn't know what the variables last is, but wasn't it just defined? Or am I doing that incorrectly?

You need to retrieve the HA global then create a time object, which you can apply getTime() to.
e.g.

let last = global.get("homeAssistant.states['device_tracker.iphone_13'].last_changed");
last = new Date(last).getTime();
let now = new Date().getTime();
let diff = now - last;
msg.payload = diff;
return msg;

Looking at your global you seem to be missing the start property homeassistant
e.g.

homeassistant.homeAssistant.states["device_tracker.my_iphone_13"].last_changed

But difficult to tell with the cropped images can you export the Copied value of the complete object?

That's it! I added a second homeassistant to the front of the path and it works!

Yeah sorry about the cropped stuff, my name is in the device name so I was trying to keep that out of it.

So what's the "theory" or understanding I need to have to know to add the homeassistant in front of everything? I'm just starting to learn Node Red and don't know javascript at all (if that isn't already painfully obvious) and with message objects I can copy the file path and that works when referencing something. But here it doesn't work. I think it is because when I look at this screenshot,

I can see homeAssistant.object is nested under homeassistant. So the path I'm copying is already "inside" the homeassistant on the left hand side.

For clarity for anyone else who comes along later, here is my final working code with my comments explaining (hopefully correctly) each line:

//Get the time of last change from HA and let that equal last
let last = global.get("homeassistant.homeAssistant.states['device_tracker.my_iphone_13'].last_changed");
//Convert this date to a time in the format of the number of milliseconds since Jan 1 1970
last = new Date(last).getTime();
// Get the current date and time and convert this as well.
let now = new Date().getTime();
// Calcuate the difference in these two. Answer is in milliseconds, so convert to minutes and round to nearest minute.
let diff = Math.round((now - last)/1000/60);
msg.payload = diff;
return msg;

Thanks so much @E1cid for helping me out here. I totally recognize I'm bumbling around here, so I appreciate your patience.

Edit to add: in the end, while I accomplished this, apparently when you request an updated location, the location is considered changed even if the zone isn't changed. Probably because the GPS is reporting back a slight difference. Ugh. Back to the drawing board....

If you copy an path from debug it does not copy the msg property, so you have to add msg. Context does the same it copies the path in the global object , so you have to add the global's initial property to.

Hope that is clear for you.

Yeah, that make sense. Thanks again!

So after I realized that requesting a location update from the phones resets the time, and the time you've been helping be get is not useful to me anymore, I had a small breakdown...

...but then I got back up and I'm pretty sure I figured out the solution to my overall problem. Just wanted to link it here so any future versions of me can find it.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.