Input_datetime.set_datetime can only update date OR time? (possible bug)

I wasn’t at a workstation so I couldn’t reply properly (theres’ only so much you can do on a phone)
Anyway here’s what I get in the template editor using : -

{% set next_date = state_attr('input_datetime.id_meds_date_statin','timestamp') %}
next {{ next_date }}
datestamp equiv {{ next_date | timestamp_custom('%Y-%m-%d %H:%M:%S') }}
{% set today = as_timestamp(states.sensor.date.last_changed) %}
today {{ today }}
datestamp equiv {{ today | timestamp_custom('%Y-%m-%d %H:%M:%S') }}
{% set delta = ((next_date - today) / (24 * 60 * 60)) | round(0) %}
delta {{ delta }}
diff {{ (next_date - today) }}
{% set days = ((next_date - today) / (24 * 60 * 60)) | int %}
which is {{ days ~ "d " ~ (next_date - today) | timestamp_custom('%H:%M', false) }}


This is just after a forced restart to help with the demostration
This demonstrates that I don’t get the proper answer (which should be a ‘delta’ of 51 days). Even when using last changed without a reboot I get 50d 23:59 (which may or maynot resolve to 51 with a little coaxing) The point is - it doesn’t generate the number I need which is 51 (in this case) hence why I did it like I did. (that’s not to say there may not be a better way but … haven’t seen one yet AND this is only at most 2 days old, I may come back and finesse it later).

For clarity : -
image

Edit : You are right about the datetime only holding the date, dunno how I missed that.
I guess I’m spending tomorrow clawing a few microseconds per evaluation back
My OCD again.
:rofl:

You already have pnbruckner and Taras on that thread (two of the best guys I know (literally !))

My two cents would be two automations and one helper (input boolean)
the normal activity is lights on at sunset-15m and off at 01:00 UNLESS input_boolean.gdoor is on.
input_boolean.gdoor is put on when (dark- obviously) and the door opens and turned off when the timer expires
You can also do the same for the other automation so the door doesn’t switch the light off at say 21:15 (or you could repeat the conditions of the sunset automation) The point is - helpers are there to help you pracis other code into an individual state that can be reused easily.

Edit: I read further and see that @septillion suggested pretty much the same thing
You shouldn’t cross thread post like this, you should maybe tag them for their attention in that thread (but that can sometimes be considered rude :man_shrugging: )

@Mutt That’s because you grab it from a last_changed. But you can fix that by rounding up or by using a date object.

So

{% set next_date = state_attr('input_datetime.id_meds_date_statin','timestamp') %}
next {{ next_date }}
datestamp equiv {{ next_date | timestamp_custom('%Y-%m-%d %H:%M:%S') }}
{% set today = as_timestamp(states.sensor.date.last_changed) %}
today {{ today }}
datestamp equiv {{ today | timestamp_custom('%Y-%m-%d %H:%M:%S') }}
{% set delta = ((next_date - today) / (24 * 60 * 60)) | round(0, 'ceil') %}
delta {{ delta }}
diff {{ (next_date - today) }}
{% set days = ((next_date - today) / (24 * 60 * 60)) | int %}
which is {{ days ~ "d " ~ (next_date - today) | timestamp_custom('%H:%M', false) }}

Or with date() (I think, harder for me to check without your variables)

{% set next_date = (now().fromtimestamp(state_attr('input_datetime.id_meds_date_statin','timestamp')).date() ) %}
next {{ next_date }}

{% set today = states.sensor.date.last_changed.date() %}
today {{ today }}

{% set delta = (next_date - today).days %}
delta {{ delta }}
1 Like

I have to admit, That’s pretty damn good

I’ve never come across the Jinja2 ceiling command before - round(0, ‘ceil’)
In Excel it’s common but then so is adding 0.5 and rounding as Excel ‘actually rounds’ (Jinja2 is a different matter, you have to test every assumption)

I also like the .date() bit which is self explanatory but the : -
(now().fromtimestamp(state_attr('input_datetime.id_meds_date_statin','timestamp')).date()
Is NOT
you’re gonna have to explain that one as I don’t see where now() comes in to it.

But the upshot I get is that : -

"{{ (states.sensor.date.last_changed.replace(hour=0,minute=0,second=0,microsecond=0) + timedelta(days=(states('input_number.in_meds_days_statin') | int))).strftime('%Y-%m-%d') }}"

Could just become : -

"{{ (states.sensor.date.last_changed.date() + timedelta(days=(states('input_number.in_meds_days_statin') | int))).strftime('%Y-%m-%d') }}"

Or even as a timestamp …

"{{ (states.sensor.date.last_changed.date() + timedelta(days=(states('input_number.in_meds_days_statin') | int))) }}"

And that my test simply use the ceiling to ensure everything is ‘bob on’

Many Thanks I’ve learned something good today

1 Like

OK–back to the original topic.

I think it’s a bug in the UI. I think I can better characterize the issue now.

I’m using core-2021.4.0, and I think it starts when you change the date and time of the widget.

When you call input_datetime.set_datetime only the time will update. Multiple calls with same date will continue only to update the time. The date will not correct itself until you make a subsequent call to input_datetime.set_datetime with a different date than the first service call. I’m fairly certain that this is different buggy behavior that I observed in core-2021.2.1 yesterday, where two calls with the same datetime would fix the issue.

Looks like it might be the same issue as #8813 that @baunan mentioned. I originally dismissed this since I assumed it would be in core-2021.4.0, but it was merged literally 3 days ago.

There is a ceil formula in Excel too.

Yeah, I have to agree with you. This is because states() always returns a string (str), whatever the datatype. Even input_datetime is just stored as a str. And second the lack of being able (as far as I know) to call constructors. So making the input_datetime a datetime-object is a bit hard.

The cheat is to grab a datetime-object, for example now(), and call fromtimestamp() on that object to have a new datetime-object with the desired date and time set. now() basically acts as pointer to the datetime Python library.

But yeah, the whole “states() always returning a str” is on my list for a What the heck month. I think it would be very useful if states() would return a suiting datatype and only revert to str if it does not know. Especially for helpers it’s always known what the expected datatype is. input_number => float, input_boolean => bool etc. A states() on an input_datetime could just return a datetime-object (or even a date-object or a time-object if it would check has_time and has_date). I mean, we also always have to add a floatorintfilter to everyinput_number`` we want to do math on :confused:

1 Like

I did a test and I’m a bit amazed…

First of, I made a test input_datetime with time and date. It was set to ‘2021-04-09 00:00:00’. Did a service call with datetime: '2021-07-08 12:34:56'. This correctly set the input_datetime without a problem. So I don’t see a bug there.

But then I played with it a bit more, setting the datetime a couple more times to different values. Looking at it from dev tools => states it updated every time. Then I opened the info. First thing I noticed is that ill will show already a change when you open up the details tab (without actually changing the values). But even weirder, this is how the history looked. Mind you, I used a couple of different date and times


The history graph does reflect that but the logbook entries all show setting it to the last value! So it seems to me the setting part is correct but the storing/retrieving from history values in the logbook is broken!

[edit]Now scanning through the GitHub issue, I think I opening details wasn’t flagged as change but it’s because a call with datetime causes two changes.

Yes, that’s what I said : -

But there’s more than one way to skin a cat - as I went on to say

There has been work on the Jinja2 interpreter.
Historically storing all values as strings was just easier.
The data arrays were just of one type.
I don’t think that’s going to change but the way the Jinja2 values are produced have (this may be the way yaml interprets them so a grey area)
Anyway, there are circumstances where you don’t get a string (it’s why testing assumptions in the templating tool is so important (but there are issues with that too (see later) ).
Most recently where stored strings have (occasionally) incorrectly been interpreted as numbers, specifically codes passed to infra-red control devices. For some reason they are seen as exponents. I don’t remember the full details as its not an area I play in (I have no devices requiring infra-red control) (I think Tom_l and Taras were in that discussion thread if you want to search).
So it seems that the ‘conversion’ (if any) is being done on the fly based on what the stored value ‘looks like’ rather than “this came from an input boolean - it must be a boolean”
You have to bear in mind any project starts with the best of intentions as yet on day one compromises are made. Given the nature of the current ‘minimum hardware recomendations’ compared to the first pass, it’s at least an order of magnitude.
Regardless, we carry our baggage with us and changing the database structure or the way values are parsed may affect many things (causing major breaking changes a cross the board would not be popular. Even your example that input numbers are float is arguable as it may have been intended as an integer (this should not affect calculations from it but … ) Generally casting an int to an int (or any number to a float) or a timestamp to a timestamp etc. Should not be a problem but will they take that risk ? You could argue that storing a value to an input number implicitly declares it a float, thus the evaluation from it should the same.

I liked your explanation as it assumes no background knowledge (the thread should be able to be read by ALL)
I think (I’m gonna have to check) that my text method of getting a timestamp is about the same length as your now() method and maybe more intuitive/readable but I’ll have to run timings on it as regardless of what I’ve said I may well go with the faster version.

TL;DR
It’s always best to test thoroughly any template, passing ranges of expected values and also checking what happens (say) when a sensor value is ‘unavailable’

Edit: I forgot about “later”
If I enter : -
{{ states | count }}
In the templating tool I get : - 1183
If I create a sensor with the same statement, it displays : - 1051
:man_shrugging:

Edit : I have since done an update to core-2021.4.1 and now ‘both’ versions report 1188

I never saw it, out of curiosity, do you have an example? I also couldn’t find a method or filter to just show the type. Only some tests for float for example.

You would say a date from datetime would look like a date :smiley:

True it could also be used as an int but at least you can do calculations with it. And “float” is how they are stored in text as well, even if you set an input_number to whole numbers only, it is stored as 3.0 etc. That’s why I think float would make sense and gives you the option to cast it to int later on.

Think the risk is pretty minimal as all those types can be printed as a str without casting. So places where they are now used as a str still work. Alternative option would be to give us at least filters or converters to the types you can already have in a template (like datetime, time and date). Just doing states()|date would already be more readable / easier.

Agreed but checking that isn’t particularly easy at the moment.

Interesting. I did a quick check and here the sensor and the template tool agree. Although only after I checked when HA was fully started, template tool didn’t update automatically.

Think that sums it up :smiley:

An example (but one of several I think) : -

When you search, you have the ‘options’ link, which gives you more ‘options’ :rofl:

Re: the unavailable problem, Petro has expounded at great length on this issue. Again search for unavailable and add Petro as the poster

The devs (for the most part) are unpaid individuals. They ‘choose’ the work they do based on what they feel capable of and what interests them. There are a few devs paid by Nabu casa but we’ve given up trying to predict where they will focus their attention.

1 Like

The issue with the history I wrote about in this thread:

All I got was “it’s being worked” with no reference to a particular defect report.

Regarding your test, all I can say is your version of software may matter, as well as the browser/OS you’re using.

I find it a bit hard to pinpoint the issue and I’m certainly not the person to open an issue about it :angel:

About software:

  • HA 2021.4.1
  • Window 10 x64
  • Firefox (I assume my laptop also uses the same version as my desktop aka 87.0 (64-bit))

Well, there you go. You’re on 2021.4.1 and I’m on 4.0. Of course, I don’t know why I wasn’t upgraded to 4.1 when I upgraded to the latest version 2 days ago.

I believe the latest version is less than two days old.

Make that less than 9 hours for 2021.4.1 :smiley: But yeah, the 2021.4 release party was Wednesday evening.

Interesting considering the date of the press release is April 7.

Probably a bug in the software with updating the date.

I have since done an update to core-2021.4.1 and now ‘both’ versions report 1188

:man_shrugging:

1 Like

Scroll down and you will see