Trigger automation 15 minutes before date_time stored in input_datetime

ok, maybe not a year ago but it felt like that

1 Like

One of the headaches of a time-only input_datetime is that it stores time as local time (not UTC). So its Unix Timestamp is referenced to the Unix Epoch not with a UTC time but with local time.

Example:
If it’s 10:45 local time 5 time zones away from UTC, the input_datetime is:
1970-01-01T10:45+00:00
However, that’s not the correct time in UTC for 10:45 because it doesn’t incorporate +05:00. Attempting to use this as a datetime object becomes a challenge because it’s several hours off.

FWIW, I had raised this as an issue several version ago when datetimes were being re-engineered. However, this was considered to be normal because a time alone cannot be expressed as a Unix timestamp (which I find to be a specious reason because there it is above, referenced to the Unix Epoch).

Well, the “timestamp” attribute is a misnomer, imho. It just holds the number of seconds since midnight local time, which is handy but not quite a Unix epoch.

today() would definitely improve a template’s legibility.

I think the shortest way to get the same result with what’s available today might be this and it’s still far from straightforward: (EDIT: meh, on second thought, still far from “shortest” especially if the 08:00 has to come from some other entity)

{{as_datetime(now().date() ~ 'T08:00').astimezone()}}

The alternative is to use now() and then replacing portions of it but that’s still verbose.

I agree it bends the definition of “timestamp” compared to how that word is used elsewhere (and fairly consistently) in Home Assistant. One discovers just how much ‘bending’ when attempting to use it as a datetime object (and one’s calculations are off by one’s timezone offset).

Anyway, it’s better now that it was 2.5 years ago (when I first started using Home Assistant) and discovered data and time calculations (a staple of home automation logic) were treated like second-class citizens. A few more ‘helper functions’ and it should make juggling date and time even easier.

That would eliminate a lot of headaches. I’d vote for that.

This makes more sense to me:
image

It breaks the “false” timestamp though.
OTOH, intput_datetime with date+time and date-only both have real timestamps, so for the sake of consistency…

The challenge presented by that proposal is that it deviates from the norm and needs to update its value on a daily basis. The other flavors of input_datetime use a fixed value.

1 Like

Just for fun, paste this into the Template Editor:

{% set t = as_datetime('1970-01-01T08:45').astimezone()%}
{{ t }}
{{ t.timestamp() }}
{{ now().fromtimestamp(t.timestamp(), now().tzinfo) }}

There’s a potential hitch with the idea of storing the time (for a time-only input_datetime) on the day of the Unix Epoch plus one’s timezone. The hitch is DST.

The result of the three templates is this (for my timezone):

1970-01-01 08:45:00-05:00
49500.0
1970-01-01 08:45:00-05:00
  • The first line represents the 08:45 as a datetime object whose date is the Unix Epoch and whose timezone is set to the local timezone. It looks good.
  • The second line is the same datetime object but converted to a unix timestamp.
  • The third line creates a datetime object from the timestamp and the result matches the original datetime object. It looks good.

Everything looks perfect except the timezone offset now, in July August, is -04:00 and not -05:00 (which is OK for January).

This poses a challenge of how to use this arrangement to set a fixed time of 08:45 (for year round use) without it being offset by DST.

I’m beginning to see why it currently works the way it does … (namely as just the number of seconds since midnight).

Yeah, no-go.

What about

My as_datetime() and `as_timestamp() don’t appear to have the same magic as yours do.

What I showed is a proposal for a change that I implemented :slight_smile:
Indeed, currently, neither as_datetime nor as_timestamp work for a time-only input_datetime

1 Like

Ah! My mistake; I didn’t understand that and thought you were demonstrating existing functionality.

I like it. It would make using a time-only input_datetime as neat as what petro proposed with a today() function:

{{ now() >= as_datetime(states('input_datetime.xyz')) - timedelta(minutes=15) }}

That happens to be the same template one can currently use if the input_datetime has both time and date.

Are you planning to create a PR?

Sure. Would be nice to get the feedback from @petro, as he already thought quite a bit about the problem.

What exactly did you change? Can you plop your changeset or branch?

Here you are

I don’t think that will pass a review. I could be wrong on that, but i would expect the changes to go in home-assistant/dt.py at 9fc92ab04e0d1933cc23e89b4095714aee725f8b · koying/home-assistant · GitHub

I want to post a detailed response but I’m on a crunch at work. I’ll have to respond in a day or 2.

1 Like

What are your thoughts on making as_datetime convert a date-only input_datetime?

For example it would convert 2021-08-20 to a datetime object with the same date but at time 00:00:00 and one’s local timezone?

Basically, it would support conversion of all flavors of input_datetime to a usable datetime object.

That’s already the case, isn’t it?

Almost, the result is offset-naive (no timezone) so you can’t use it in a comparison with an offset-aware datetime object like what’s produced by now() or in date math.

Per ISO, no TZ means local time.
If I do

{{ as_timestamp(as_datetime(states('input_datetime.date_only'))) }}

I get a timestamp of 00:00 in my local time.