How to reference sensor in the today_at() statement

Good day, I have tried to use the today_at statement referencing a sensor but it doesn’t return a proper time.

I have tried quotes, no quotes, using the unique name, using the sensor name, with or without .isofformat() all without success.

Any suggestions for what goes into the today_at() line starting with:
state: "{{ (today_at(sensor.ktch_light_morning_on).isoformat()

I want to create a random time that is based on the KtchLightMorningOn sensor.

code from configuration.yml:

template:
  - trigger:
      - platform: time
        at: '00:00:00'
      - platform: event
        event_type: event_template_reloaded
    sensor:
      - name: 'LvrLightMorningOn'
        unique_id: 'lvr_light_time_on'
        state: "{{ (today_at('06:17:00') + timedelta(minutes = range(0,23) | random)).isoformat() }}"
        device_class: timestamp
      - name: 'LvrLightEveningOff'
        unique_id: 'lvr_light_time_off'
        state: "{{ (today_at('21:41:00') + timedelta(minutes = range(0,37) | random)).isoformat() }}"
        device_class: timestamp
      - name: 'KtchLightMorningOn'
        unique_id: 'ktch_light_morning_on'
        state: "{{ (today_at('06:18:00') + timedelta(minutes = range(0,21) | random)).isoformat() }}"
        device_class: timestamp
      - name: 'KtchLightMorningOff'
        unique_id: 'ktch_light_morning_off'
        state: "{{ (today_at(sensor.ktch_light_morning_on).isoformat() + timedelta(minutes = range(0,21) | random)).isoformat() }}"
        device_class: timestamp

Hello bizckwright,

Thanks for coming here and asking a question.
Would you be so kind as to adjusting the format of your code so that we can read it properly & check the YAML spacing, etc. Editing your original is the preferred way. It is very hard for us to tell what is what when the text formatter jumbles everything like that.
You can use the </> button like this… How to format your code in forum posts
OR… Here is an example of how to fix it from the site FAQ Page.
How to help us help you - or How to ask a good question.

Thanks, edited now for the formatting

1 Like

We’d need to know what state the entity has. Can you go to developer tools → states, search for sensor.ktch_light_morning_on, and report back here what its state is?

Thanks Rick, I appreciate the help. and that is neat to see that the values are listed there, good for troubleshooting.

sensor.ktchlightmorningon = 2025-10-11T13:21:00+00:00

image

One of the most important things when using templates is knowing what type of data you have, and what type you need for what you want to do.

The function today_at() expects a time string in “HH:MM” or “HH:MM:SS” format and returns a localized datetime object.

Your sensor’s state is a datetime string, so you need to extract the time portion to use it in today_at().

Here are two ways to do that:

# Using datetime methods
{{ today_at((states('sensor.ktch_light_morning_on')|as_datetime).time()) }}


# Using string slicing
{{ today_at(states('sensor.ktch_light_morning_on')[11:19]) }}

Keep in mind that timedelta() is a datetime method, it only works on datetime objects. The method isoformat() returns a string from a datetime object, so do not use it until all the datetime object-related functions are completed.

...
state: |
  {% set rand_min = range(0,21) | random %}
  {% set time_string = (states('sensor.ktch_light_morning_on')|as_datetime|as_local).time() | string %}
  {% set today_time = today_at(time_string) %}
  {{ (today_time + timedelta(minutes = rand_min)).isoformat() }}
1 Like

Thanks everyone, I really appreciate the quick and friendly help.

One last question, when I add in that code, it works but it adds about 7 hours between the on and the off sensors (the random minutes looks good, staying within the up to 21 minute difference).

Any thoughts on why it says 20: when the on says 13:?

First, make sure you are using the correct entity IDs… what is shown in your screenshot is not what you provided us in the original post.

Second, any time things are offset by whole hours, timezones should be double checked. Is your HA instance properly set to your local timezone?

One of the benefits of using variables in templates is that you can check each step in the chain by pasting it into the Template tool and adding expressions for each variable:

  {% set rand_min = range(0,21) | random %}
  {% set time_string = (states('sensor.ktch_light_morning_on')|as_datetime|as_local).time() | string %}
    {{ time_string }}
  {% set today_time = today_at(time_string) %}
    {{ today_time }} 
  {{ (today_time + timedelta(minutes = rand_min)).isoformat() }}

Thanks, I’ll muddle my way through this remaining issue. The sensor.ktchlightmorningon is needed versus sensor.ktch_light_morning_on as that doesn’t return a value. Anyway, I will look for where the extra 7 hours is coming in.

I appreciate everyone’s assistance, that was most helpful.

Chris