Random time: time helper set through automation is one hour off

For faking presence and switching off lights in holiday mode, I wanted to have a random “bedtime”, somewhere between 22:00 and 23:59. I use that within a script.

The only way to randomize is with integers, so I came up with the following random sensor for a timestamp:

sensor:
- platform: random
    name: "Random bedtime timestamp"
    minimum: 79200     # seconds after 00:00 = 22:00:00
    maximum: 86399    # seconds after 00:00 = 23:59:59

This generates an integer which reflects the number of seconds past midnight and changes every 30 seconds.

To switch off the light at a specific time in an automation, you can use a specific (set) time or a time helper. The specific time isn’t useful, so I use an automation once a day which sets the timestamp into a time helper by doing:

service: input_datetime.set_datetime
data:
  timestamp: '{{ states("sensor.random_bedtime_timestamp") | int - 3600 }}'
target:
  entity_id: input_datetime.random_bedtime

This all works fine, but it sets my hour one off, so instead of 23:49 I get 0:49. That’s why in the code above I subtracted 3600 seconds.
Now I live in the Netherlands which is UTC+1 and this maybe why it is set one hour off. But why is this? I set a specific timestamp to a time helper, so I was expecting that to format nicely to the intended time.

Is this intended behavior or a bug?
And what happens when we change to winter time next October?
Any ideas of doing this in a more consistent way?

Thanks!

I use a similar method with an automation setting an Input datetime, but there is no need to have a Random sensor refreshing every 30 seconds for something that is only needed once a day. Instead, use Jinja’s built-in functions to render your value only when the service is called:

service: input_datetime.set_datetime
data:
  datetime: >
    {{ today_at('22:00') + timedelta(seconds = (range(0,7199)|random)) }}
target:
  entity_id: input_datetime.random_bedtime

Since today_at() is timezone-aware it should solve your hour off issue as well.

Keep in mind that using a date & time Input datetime has the drawback that the value is only good for a single day… if your automation doesn’t fire for any reason, the light will not turn off that night. You can avoid this (but possibly sacrifice a small amount of randomness) by using a time-only Input datetime:

service: input_datetime.set_datetime
data:
  time: >
    {{ (today_at('22:00') + timedelta(seconds = 
    (range(0,7199)|random))).strftime("%H:%M:%S") }}
target:
  entity_id: input_datetime.random_bedtime_timeonly
2 Likes

Nice solution, thanks: I have been searching through Jinja to get it done, but couldn’t find anything satisfying.

Well that’s the exact problem, therefore I’d rather have just a time helper.

Great bonus.
I started thinking about my problem and it seems the input_datetime.set_datetime service needs a timestamp which is UNIX format and thus always UTC. So there’s the explanation for my hour off.

However, there’s still some weirdness. When I set a time helper manually to 22:00:00 and inspect it’s attributes I get the timestamp as a local timestamp, 79200. Either the time helper is UTC (but it’s used as a local time in automations) or there’s a flaw there. To be consistent I would have expected 79200-3600 = 75600 there. It has been putting me on the wrong foot.

{{ states('input_datetime.day_end_time') }}
{{ state_attr('input_datetime.day_end_time', 'timestamp') }}

I will keep thinking about the best solution, thanks for your input.

I tried your solution, the last one with just the time and this is working perfect for me. Thanks!

1 Like

Apologies for reviving an old thread.

I’ve used your solution for a while now and it works brilliantly.

I’m now trying to make a second one that sets the time to “now + x seconds” but I don’t know what to amend the code to.

I was hoping you could show me?

I appreciate it’s Christmas Eve so feel free to ignore me! Merry Christmas!

It’s a little unclear what you mean, in context of the original question…

Do you mean just now + x seconds? That would be as follows

service: input_datetime.set_datetime
data:
  time: |
    {{ (now() + timedelta(seconds = 30)).strftime("%H:%M:%S") }}
target:
  entity_id: input_datetime.bedtime_timeonly

But if you mean now + x seconds and keep the 2 hour span of randomness, it would be:

service: input_datetime.set_datetime
data:
  time: |
    {{ (now() + timedelta(seconds = 30 +
    (range(0,7200)|random))).strftime("%H:%M:%S") }}
target:
  entity_id: input_datetime.random_bedtime_timeonly

Thanks Drew. I meant now + the random span, apologies if that wasn’t clear, so that second option should do the trick.

Much appreciated!

1 Like