Add days to input_datetime using timedelta

Hello everyone,

How do I use timedelta with an input_datetime? I want to use this to get notified when certain things need to happen.

# when the filter was last changed
{% set changed = states('input_datetime.fridge_1_filter_changedate') %}

# when to get notified (elapsed days since changed date) 
{% set change_days = states('input_number.fridge_1_filter_days')  | int %}

{{ changed + timedelta(days=change_days) }}

Template editor show following in the outputā€¦

TypeError: can only concatenate str (not "datetime.timedelta") to str

I understand that ā€˜changedā€™ is a string.

Can I change it to a datetime so I can add some amount of time on to it? If not, what is the best approach to accomplish my goal?

Thanks!

There are several ways to do it. Yes, you can convert the input_datetimeā€™s state to a datetime object using strptime.

{{ strptime(states('input_datetime.fridge_1_filter_changedate'), '%Y-%m-%d %H:%M:%S')
   + timedelta(days=change_days) }}

The result is a datetime object.

Alternately, you can leverage the fact an input_datetime has a timestamp attribute. We can add change_days to it (in seconds) then convert the result to local time.

{{ state_attr('input_datetime.fridge_1_filter_changedate', 'timestamp')
   + timedelta(days=change_days).seconds | timestamp_local() }}

The result is a string.

Appreciate it!

1 Like

timedelta() has turned out to be much less useful than I thought it would be because my datetime helpers arenā€™t datetime objects.

1 Like

Valiant effort my friend! Thanks for your contribution. Would there be clever way to turn the datetime helpers into datetime object? Maybe a config option like the has_date: ?

No, because the State value of all entities is a string. Unless that convention changes, you canā€™t have datetime helpers with a State type that differs from all other entities.

However, an entityā€™s attributes can be other types. An enhancement would be to allow datetime helpers to have an attribute containing a proper datetime object. Assuming this new attribute was called dto, your template would look like this:

{{ state_attr('input_datetime.fridge_1_filter_changedate', 'dto')
   + timedelta(days=change_days) }}

The result would be a datetime object.

1 Like

@tom_l Do you think this would be a welcomed enhancement to the input_datetime helpers? If so, easily implemented?

Yes it would but Iā€™m not sure it is possible as all entity states are strings. Itā€™s only the attributes that can have other types.

Itā€™s wishful thinking. Thereā€™s little chance of the development team agreeing to make an input_datetimeā€™s state type different from all other entities. The structure of the State Object is common to all entities.

A more plausible request would be to allow a state value to have different types (not only string) just like attributes can. In other words, the enhancement is for all entities, not just input_datetime. However, this would represent a monumental change. Most everything in Home Assistant that uses an entityā€™s state value expects the type to be string.

If you feel strongly about it, post your idea as an Issue in the GitHub Architecture repo. Discussing it here isnā€™t likely to reach the people who can implement it. If you do post it, it will have to be a reasoned proposal and not simply ā€œit would be welcomed by usersā€. Good luck!

1 Like

@123 @tom_l

Itā€™s not a big deal. Iā€™m happy with what I have. Thanks!

Coming back to this after an exchange on Discord. How would you folks feel about helpers providing an attribute whose value is equal to the state, but retaining the native type? boolean for input_boolean, float (probably) for input_number, datetime for input_datetime, etc. That way, we donā€™t have to worry about how states are represented, and provide simpler options for using typed values.

1 Like

I would like it but how would that work for an input datetime with just a date or just a time?

Itā€™s still a datetime object, right?

No. Thatā€™s the problem.

To be a datetime object you have to have a date and a time. I suppose we could substitute today at 00:00 for any missing information.

From the code, itā€™s all based on a private datetime object:

    @property
    def state(self):
        """Return the state of the component."""
        if self._current_datetime is None:
            return None

        if self.has_date and self.has_time:
            return self._current_datetime.strftime(FMT_DATETIME)

        if self.has_date:
            return self._current_datetime.strftime(FMT_DATE)

        return self._current_datetime.strftime(FMT_TIME)

And it looks like it does start with today at 00:00:

        default_value = py_datetime.datetime.today().strftime("%Y-%m-%d 00:00:00")
1 Like

Ah, ok then. Looks like the typed attribute should work. :+1:

Feature request is here, ripe for the voting :slight_smile:

If a timedelta is based on today, does that mean it cannot handle 24 hours or more? Because if it is supposed to handle more than 24 hours (which I hope) a timedelta will suddenly change value at midnight. The whole point of having a timedelta type is because people should realize a timestamp is not a duration of time. If you want to (mis)use a timestamp it, the offset should be a constant.