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

Hi everyone,

I’m using some input_datetime helpers with both date and time enabled, and I noticed that the service seems only to be able to update date OR time with a single call. If both the current date and time are different than the new date and time, only the date will be updated. A subsequent call will update the time.

Example:
Current value: 2021-04-07 00:02:00
Service argument: 2021-04-08 01:00:00
New value: 2021-04-08 00:02:00

I recreated this behavior using both timestamp and datetime arguments, as well as fixed and variable times:

timestamp: "{{ now().timestamp() }}"
datetime: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
datetime: "2021-04-09 01:02:03"

Would appreciate confirmation of this behavior from at least one other person.
I am running core-2021.2.1

Thanks.

The first thing you will have to do before submitting an issue is update to the latest version and confirm it still occurs.

According to the docs you should be able to do this.

To set both the date and time in the same call, use date and time together, or use datetime or timestamp by itself. Using datetime or timestamp has the advantage that both can be set using one template.

Can you show your config for the service call?

TBH, I’m scared something else will break, but I’ll try it.

Ha! Read the breaking changes and fix anything that needs doing.

Also make a snapshot/backup and copy it off your system first.

I updated my last comment with a bit more info.

I can confirm there is something wrong.
I have an automation that sets the last time the alarm panel changed state and it does not look right.
I’ll see in a few minutes when everyone leaves the house. But it does look strange.

It used to work but I haven’t looked at this entity for a while.

I upgraded, and now I see new fancy ways to select the date, time or datetime for this service. By default, it appeared to have “time” and “datetime” selected. I unselected time, but it seems not even to be updating the date now consistently after a second try.

  action:
  - service: input_datetime.set_datetime
    data:
      datetime: '2021-04-08 03:00:04'
    target:
      entity_id: input_datetime.driveway_light_last_manually_switched
service: input_datetime.set_datetime
data:
  timestamp: "1617860640.002738"
target:
  entity_id: input_datetime.driveway_light_last_manually_switched

I have been able to get the date and time to update in a single call (maybe when the old date was in the future?) but I’ve yet to nail down an exact pattern. I’ll second what @Hellis81 said and leave it at “there is something wrong”

I’ll try to investigate more tomorrow.

It was reported something wrong with the datetime function some time ago. Got a message that it was multiple issues which now have been solved some days ago, see #8813. So I hope thisone solves your problem.

1 Like

This is what it looks like now:

using automation:

alias: alarm last state change update
description: ''
trigger:
  - entity_id: alarm_control_panel.sector_alarmpanel
    platform: state
condition: []
action:
  - data:
      datetime: '{{ now().strftime(''%Y-%m-%d %H:%M:%S'') }}'
    data_template:
      datetime: '{{ now().strftime(''%Y-%m-%d %H:%M:%S'') }}'
    entity_id: input_datetime.alarm_last_state_change
    service: input_datetime.set_datetime
mode: single

Something is definitely wrong

@Hellis81 Why do you have a data and a data_template with the same content?

Is it still weid if you simply do

alias: alarm last state change update
description: ''
trigger:
  - entity_id: alarm_control_panel.sector_alarmpanel
    platform: state
condition: []
action:
  - data:
      timestamp: '{{ now().timestamp() }}'
    entity_id: input_datetime.alarm_last_state_change
    service: input_datetime.set_datetime
mode: single

Because at least when I wrote that, you could not get it to set with only one of them.
You needed both for it to set at all. perhaps it’s different now.
That automation is probably close to a year old with no modifications.

This is kinda funny (peculiar) I just finished (yesterday) messing with a new package to handle medications etc. And a major part of that was setting an input_datetime to a templated value
I remember going through about 8 interations trying to nail down what was going wrong.
Anyway, when I got it working I repeated (yaml cut and paste) the exact same automation 6 more times then changed the names of the usual subjects suspects.
I remember thinking “This is far harder than the last time I did this” (I had done some time only issued before this but this is date related, and I just thought “meh !” )

Anyway, this is what worked for me.
No idea if it will help you : -

  - alias: au_meds_sensors_to_off
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: input_boolean.ib_meds_order_sensors
        to: 'off'
    action:
      - service: input_datetime.set_datetime
        target:
          entity_id: input_datetime.id_meds_date_sensors
        data:
          date: "{{ (states.sensor.date.last_changed.replace(hour=0,minute=0,second=0,microsecond=0) + timedelta(days=(states('input_number.in_meds_days_sensors') | int))).strftime('%Y-%m-%d') }}"

Edit: just re-read and your problem is date AND time - sorry

It is very cumbersome, and arguably unnecessarily. I have to create an automation and an input_datetime to record the last changed time of every motion sensor I have, since the built-in attribute last_changed doesn’t survive reboots (gets reset). There was an effort last year to get the behavior to change which seemed to die.

I’ll give this some more investigation later in the day.

1 Like

@Hellis81 As far as I know it was always sufficient to have a ‘data’ or a ‘data_template’ or both but not mandatory. As ‘data’ can now do templating as well, ‘data_template’ is now deprecated.

@Mutt You can do it simpler :slight_smile:

  - alias: au_meds_sensors_to_off
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: input_boolean.ib_meds_order_sensors
        to: 'off'
    action:
      - service: input_datetime.set_datetime
        target:
          entity_id: input_datetime.id_meds_date_sensors
        data:
          timestamp: "{{ (states.sensor.date.last_changed + timedelta(days=(states('input_number.in_meds_days_sensors')|int) )).timestamp()"

Ha ! No, I tried that first and as I was testing it became apparent that if I restart ha then sensor date last changed becomes the time of the restart (if it was the same day) thus the calculation I do subsequently is thrown off. I decided to head it off at the pass and do it with belt, braces and a bit of string.
:rofl:

Doesn’t your version still suffer from the same last_changed restart problem? You’re still using states.sensor.date.last_changed.

@Mutt I’m wondering the same as @tgpaul… I don’t see how you will get a different result now.

@tgpaul @septillion

No, if you look at ‘my’ posted code it takes the last changed then discards any hours, minutes, seconds and microseconds since midnight.

You got me thinking though and I do use time AND date to track when my heating was last ‘on’ and ‘off’ : -

  - alias: au_heat_boiler_last_onoff
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: switch.boiler_switch
        from: 'on'
        to: 'off'
      - platform: state
        entity_id: switch.boiler_switch
        from: 'off'
        to: 'on'
    condition:
      - condition: template
        value_template: "{{ states('sensor.s_ha_uptime') != '00:00' }}"
    action:
      - service: input_datetime.set_datetime
        data_template:
          entity_id: input_datetime.id_heat_last_{{trigger.to_state.state}}
          datetime: "{{ now().strftime('%Y-%m-%d %H:%M'~':00') }}"

And before you ask, the high specificity on the triggers is to remove any attribute change of the switch from updating the times of the events I wish to monitor.

Edit: Linux measures time in seconds but … using an Excel analogy which measures time as a float (ie. integers = days and decimals = time within that day) for Excel you integerise the now() then you have the midnight - this is the same principle.

I thought this would produce the number of seconds since the Unix epoch (Jan 1, 1970 00:00:00). As I see it, you’re still using the date which will reset on reboot. If your template doesn’t actually care about the date being accurate, you can simplify your stuff even more.

Where is it documented that timestamp is days.fractional_days? This is definitely not seconds if that’s the case.

@Mutt Why store the time when you set it to midnight anyway? Why not just make a input_datetime with only date? After all, you ony set the date…

So no, I don’t see any difference… :smiley:

The difference between the ‘actual’ last changed and an normally occuring ‘midnight’ change is sufficient to throw off the ‘timestamp’ of the set input_datetime. In fact the actual midnight change generally gives me a timestamp that is about 0.78 seconds past midgnight which just offends the OCD in me.
The actual restart (mid-day somewhere) throws off a count down I have running to count the days to when I need to re-order meds.
This REALLY upsets the OCD in me when the countdown is off by 1 day on the day of the restart.