Edit Calendar Entry

Not for this. Technically, you don’t need either of them; they are just an organizational tool.
There are a number of ways to split the configuration. Personally, I prefer Packages.

Assuming you have properly merged them in your configuration.yaml file, the sensor.yaml file is for configuring entities under the Sensor integration and template.yaml is for entities under the Template integration. While it is possible to create template sensors under the Sensor integration, this is not the preferred method and it they do not support all the current features and abilities. The sensor configuration I shared uses a trigger (which is not supported by the Sensor integration) and follows the syntax for the Template integration.

You copy the entire configuration in Post #8 and paste it into you template.yaml file.

Then you need to go to the Server Controls and either Restart Home Assistant or reload Template Entities. If you haven’t restarted since you first added anything into that file, you need to restart. If there are other things in that file that have already been properly loaded, you can just scroll down the list to Template Entities and click to reload just the Template integration.

The sensors do not exist despite placing your code in Post #8 in template.yaml and rebooting Home Assistant. Easy Time Jinja is in config/custom_template/easy_time.jinja.

I decided to start over and restore my proxmox backup to a date before I started messing with this. I added experimental to HACS and then installed the easy_time.jinja with the link vs manually installing. Added you template.yaml file code and added it the config.yaml file. By some miracle the sensors showed up and I can now label them.

After enabling the experimental setting in HACS I noticed my Frigate, Mushroom and Battery Card frontends don’t load. I get the error You have 3 Lovelace elements that are not loaded properly in Lovelace. I can redownload the frontends and the error goes away but comes back after a reboot. Any ideas on how to fix it.

The HACS errors are gone don’t know what I did to fix it.

Now that I have sensors created I was thinking about other use cases.
Labeling holidays that are days off from work and then send notification to turn my alarm off and then back on again the next day.

Do you have a script that I could modify that would add holidays to a calendar with a certain label? I’ve tried to adapt your current script but by jinja is very limited at this time. Thanks

This is what I have so far but I’m not get each entry in the array to print

{%- set ns = namespace(work_holiday= [] ) %} 
{%- set holiday= expand(label_entities('Work Holiday')) %}
{%- for i in holiday %}
  {{ state_attr( 'holiday [i]', 'friendly_name') }}
  {{ states('holiday [i]') }}
{%- endfor %}

Result type: string

None unknown None unknown None unknown None unknown None unknown None unknown

This template listens for the following state changed events:

* **Entity**: holiday [i]
* **Entity**: sensor.christmas
* **Entity**: sensor.independence_day
* **Entity**: sensor.labor_day
* **Entity**: sensor.memorial_day
* **Entity**: sensor.new_years_day
* **Entity**: sensor.thanksgiving

I think what you were going for is:

{%- set ns = namespace(work_holiday= [] ) %} 
{%- set holiday= label_entities('Work Holidays') %}
{%- for i in holiday %}
  {{ state_attr( i, 'friendly_name') }}
  {{ states(i) }}
{%- endfor %}

Be aware that you cannot use a simple loop like that for a Repeat for Each action to populate calendar event entries. You defined a namespace, but you did not use it so the loop is just returning a block of text. Repeat for each requires an actual list/array of simple objects like strings, lists, or dictionaries.

alias: Calendar - Populate Holiday Calendar
sequence:
  - variables:
      date_list: >
        {%- set ns = namespace(holidays= []) %} 
        {%- set holiday= expand(label_entities('Work Holidays')) %}
        {# Loop through holiday sensor state objects and create a list of dicts with required calendar event data#}
        {%- for each in holiday %}
          {%- set date = each.state%}
          {%- set isoweekday = (date|as_datetime|as_local).isoweekday() %}
          {%- if isoweekday not in [6, 7] %}{# Only create Cal event if on a weekday #} 
             {%- set ns.holidays=ns.holidays + [
              {"summary": each.attributes.friendly_name,
              "description": "Work Holiday",
              "start_date": date,
              "end_date": (date|as_datetime|as_local + timedelta(days=1)).date()|string}] %}
          {%- endif %}
        {%- endfor %}
        {{ ns.holidays | sort(attribute="start_date")| rejectattr("start_date", "lt", today_at()|string) | list }}
  - repeat:
      for_each: "{{date_list}}"
      sequence:
        - service: calendar.create_event
          data:
            summary: "{{ repeat.item.summary }}"
            description: "{{ repeat.item.description }}"
            start_date: "{{ repeat.item.start_date }}"
            end_date: "{{ repeat.item.end_date }}"
          target:
            entity_id: calendar.work_holidays
        - delay: 2
mode: single
icon: mdi:calendar-edit-outline

EDIT: Fixed variable names in service call and end_date template.

1 Like

if you’re interested in editing local calendar events, vote for it here:

1 Like

Thanks for the update on the code will give it try after I get the sensors working again.

I noticed that you edited the Easy Time Version to fix the ‘Variable Date’ section. When I copy the new code into the template.yaml and restart HA I get unavailable for the state of any of the sensors.
The log file shows

Logger: homeassistant.config
Source: config.py:622
First occurred: 2:28:06 PM (7 occurrences)
Last logged: 2:42:47 PM

Invalid config for 'template' at template.yaml, line 2: 'template' is an invalid option for 'template', check: template

Not sure what’s wrong.

# Trash Holidays: new years, independ, memorial, labor, christ, thanks
template:
  - trigger:
      - platform: time
        at: "00:01:00"
      - platform: state
        entity_id: input_button.update_holiday_sensors
      - platform: homeassistant
        event: start

    # FIXED DATE

    sensor:
      - name: "New Years Day"
        unique_id: "37319374975705055206"
        state: >
          {% from 'easy_time.jinja' import month_day %}
          {{ (month_day(1, 1)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_day %}
            {%- set x = ((month_day(1, 1)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: "Dia de Los Reyes"
        unique_id: "1984497531937520705056"
        state: >
          {% from 'easy_time.jinja' import month_day %}
          {{ (month_day(1, 6)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_day %}
            {%- set x = ((month_day(1, 6)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: "Valentines Day"
        unique_id: "22719844595073910047"
        state: >
          {% from 'easy_time.jinja' import month_day %}
          {{ (month_day(2, 14)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_day %}
            {%- set x = ((month_day(2, 14)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: "Saint Patricks Day"
        unique_id: "44595073912271980047"
        state: >
          {% from 'easy_time.jinja' import month_day %}
          {{ (month_day(3, 17)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_day %}
            {%- set x = ((month_day(3, 17)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: Halloween
        unique_id: "947396278926815041"
        state: >
          {% from 'easy_time.jinja' import month_day %}
          {{ (month_day(10, 31)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_day %}
            {%- set x = ((month_day(10, 31)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: Dia de Muertos
        unique_id: "9750858485431103467"
        state: >
          {% from 'easy_time.jinja' import month_day %}
          {{ (month_day(11, 2)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_day %}
            {%- set x = ((month_day(11, 2)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: Rex Manning Day
        unique_id: "4690662543745975107"
        state: >
          {% from 'easy_time.jinja' import month_day %}
          {{ (month_day(4, 8)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_day %}
            {%- set x = ((month_day(4, 8)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: Christmas
        unique_id: "14318885502034384968"
        state: >
          {% from 'easy_time.jinja' import month_day %}
          {{ (month_day(12, 25)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_day %}
            {%- set x = ((month_day(12, 25)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: "Veterans Day"
        unique_id: "31975705053740693752"
        state: >
          {% from 'easy_time.jinja' import month_day %}
          {{ (month_day(11, 11)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_day %}
            {%- set x = ((month_day(11, 11)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: Independence Day
        unique_id: "9084317551034684857"
        state: >
          {% from 'easy_time.jinja' import month_day %}
          {{ (month_day(7,4)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_day %}
            {%- set x = ((month_day(7, 4)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      # VARIABLE DATE

      ## MONTH WEEK DAY

      - name: "Martin Luther King Jr"
        unique_id: "496217893819475026"
        state: >
          {% from 'easy_time.jinja' import month_week_day %}
          {{ (month_week_day(1, 3, 1)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_week_day %}
            {%- set x = ((month_week_day(1, 3, 1)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: "Mothers Day"
        unique_id: "749819475062189326"
        state: >
          {% from 'easy_time.jinja' import month_week_day %}
          {{ (month_week_day(5, 2, 7)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_week_day %}
            {%- set x = ((month_week_day(5, 2, 7)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: "Fathers Day"
        unique_id: "962741899473268150"
        state: >
          {# third Sunday of June #}
          {% from 'easy_time.jinja' import month_week_day %}
          {{ (month_week_day(6, 3, 7)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_week_day %}
            {%- set x = ((month_week_day(6, 3, 7)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: Thanksgiving
        unique_id: "69425309251060427914"
        state: >
          {# 3rd Thursday in November #}
          {% from 'easy_time.jinja' import month_week_day %}
          {{ (month_week_day(11, 4, 4)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_week_day %}
            {%- set x = ((month_week_day(11, 4, 4)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: Memorial Day
        unique_id: "20611770923315821822"
        state: >
          {# last Monday in May #}
          {% from 'easy_time.jinja' import last_day_in_month %}
          {{ (last_day_in_month(5, 1)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import last_day_in_month %}
            {%- set x = ((last_day_in_month(5, 1)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
          availability: "{{ now() is defined }}"

      - name: Labor Day
        unique_id: "78754309251267813130"
        state: >
          {# 1st Monday in September #}
          {% from 'easy_time.jinja' import month_week_day %}
          {{ (month_week_day(9, 1, 1)|as_datetime).date() }}
        attributes:
          days_until: >
            {%- from 'easy_time.jinja' import month_week_day %}
            {%- set x = ((month_week_day(9, 1, 1)|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      ## LUNAR-DERIVED

      - name: "Mardi Gras"
        unique_id: "734459509122779462132"
        state: >
          {% from 'easy_time.jinja' import easter %}
          {{ (easter()|as_datetime - timedelta(days=47)).date() }}
        attributes:
          days_until: >
            {% from 'easy_time.jinja' import easter %}
            {% set x = ((easter()|as_datetime 
            - timedelta(days=47)) - today_at()).days%}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

      - name: "Easter"
        unique_id: "189497506268132794"
        state: >
          {% from 'easy_time.jinja' import easter %}
          {{ easter() }}
        attributes:
          days_until: >
            {% from 'easy_time.jinja' import easter %}
            {% set x = ((easter()|as_datetime) - today_at()).days %}
            {{ iif(x < 1, x + 365, x) }}
        availability: "{{ now() is defined }}"

    # SEASONS
    binary_sensor:
      - name: Christmas Season
        unique_id: christmas_season_0001
        state: |
          {% set n = now() %}
          {% set offset = 'T00:00:00-05:00' %}
          {{  (states('sensor.thanksgiving')~offset)|as_datetime <= n or 
          n < (states('sensor.dia_de_los_reyes')~offset)|as_datetime }}

You copied the template: top-level key, which isn’t needed in your template.yaml file.

The normal (but unenforced) convention on this forum is to post YAML configuration as-if it is being used in the configuration.yaml file. Users who elect to split their configuration assume the responsibility to modify examples to meet their own needs, since there is no way for anyone else to know exactly how they have set up their splitting and merging.

1 Like

Your knowledge of HA and jinja are impressive. There are so many little issues that are difficult to be aware of and updates to keep track of. Any recommended reading on Jinja other than . The script works great. I just have to figure out how to run it on Dec 31 each year.

There’s no single source that covers all the things you can do with templates in HA, but make sure to check out:

Home Assistant Templating: This is the the most comprehensive source for HA-specific functions.

Forum members have been working on some cookbook-type articles. So far there is only one in the basic templates section: Community Cookbook - Templating - Getting Time and Date

Jinja for Ninjas: @skalavala has put together a well organized tutorial and group of examples. It’s been a while since this was updated, so there are better/easier ways to do some of the things shown, but it’s still a good source.

Many Python methods also to work in templates. I’ve never seen a complete list of which methods work and which don’t… But the Official Python docs have come in handy for me multiple times to figure out what’s going on in templates posted by some of the more advanced users on this forum.

1 Like

Thanks for the great links.

I notice these errors in my logs. Do you think it’s an issue in the template.yaml file you created?

Logger: homeassistant.components.template.template_entity
Source: components/template/template_entity.py:197
integration: Template (documentation, issues)
First occurred: 9:31:43 PM (1 occurrences)
Last logged: 9:31:43 PM

TemplateError('TypeError: '<=' not supported between instances of 'NoneType' and 'datetime.datetime'') while processing template 'Template<template=({% set n = now() %} {% set offset = 'T00:00:00-05:00' %} {{ (states('sensor.thanksgiving')~offset)|as_datetime <= n or n < (states('sensor.dia_de_los_reyes')~offset)|as_datetime }}) renders=4>' for attribute '_state' in entity 'binary_sensor.christmas_season'

Logger: homeassistant.helpers.event
Source: helpers/template.py:587
First occurred: 9:31:43 PM (1 occurrences)
Last logged: 9:31:43 PM

Error while processing template: Template<template=({% set n = now() %} {% set offset = 'T00:00:00-05:00' %} {{ (states('sensor.thanksgiving')~offset)|as_datetime <= n or n < (states('sensor.dia_de_los_reyes')~offset)|as_datetime }}) renders=2>
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 585, in async_render
    render_result = _render_with_context(self.template, compiled, **kwargs)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 2600, in _render_with_context
    return template.render(**kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.12/site-packages/jinja2/environment.py", line 939, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 3, in top-level template code
TypeError: '<=' not supported between instances of 'NoneType' and 'datetime.datetime'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 713, in async_render_to_info
    render_info._result = self.async_render(
                          ^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 587, in async_render
    raise TemplateError(err) from err
homeassistant.exceptions.TemplateError: TypeError: '<=' not supported between instances of 'NoneType' and 'datetime.datetime'

Fixed the template error by commenting out the seasons sensor.

# SEASONS
#binary_sensor:
#  - name: Christmas Season
#    unique_id: christmas_season_0001
#    state: |
#      {% set n = now() %}
#      {% set offset = 'T00:00:00-05:00' %}
#      {{  (states('sensor.thanksgiving')~offset)|as_datetime <= n or
#     n < (states('sensor.dia_de_los_reyes')~offset)|as_datetime }}

Hi, I’m a complete newbie, but when I copy this script into my scrips.yaml file I get the following error on line 36 ([{“summary”: “Trash Night”, ): “can not read a block mapping entry; a multiline key may not be an implicit key”. I’ve searched a lot and I can’t figure out how to fix this. Any help is appreciated. Regards.

  • Are you sure you did the rest of the script’s configuration properly?
  • Do you have all the requisite sensors, calendars, labels, etc set up?
  • Are you sure this script meets your needs? When it runs to completion, it will populate 52 calendar events that you will have to delete manually if they are incorrect.

Personally, for a new user, I would suggest not trying to add this directly into scripts.yaml. Start a new script in the UI script editor, then click the expansion menu (3-dots) at the top right and select “Edit in YAML”, then paste the configuration there.

First of all, thank you for your answer.
My answer is “no” to your three questions. I’m doing a bit of research on everything, YAML language, Templates, etc. Specifically, I was looking for information on how to have a calendar-triggered automation notify the time (just the time, not the day) of the event and then I found this forum thread, which I found very interesting.
I tried to implement it, starting by installing easy time and then copying the script into my script file, but I ran into the problem. Everything I’ve found tells me that it’s a syntax problem in YAML. I just did what you advised, pasting your script into the YAML editing mode of the scripting UI and I get the same error on the same line: “can not read a block mapping entry; a multiline key may not be an implicit key”. I’d like to know how you don’t have that problem and what that problem consists of. Best regards.

That error message normally means that you have some part of a multi-line template improperly indented. I’ve checked the template in Post #2, and all the indents seem to be properly indented. Sometimes copy/paste can introduce indent errors.

Double check your template for the following:

- variables:
    date_list: >
      {# Nothing in the rest of 
      this template should be 
      further to the left than the 
      "t" in "date_list" above. #}

Oh, great! It was a mistake when copying. This line was broken and its second part was incorrectly indented:

        {%- set first = d +
timedelta(days = 2-d.weekday() ) %} 

The funny thing is that it wasn’t the line that was flagging me as an error (also in jsonformatter.org), but one two lines earlier. Now everything is fine and I’ve learned something new, thank you very much!

Hi again. I don’t want to overdo it, but I’m facing a new problem. I’ve created the calendar (calendar.trash_night), the template sensors from “holidays_template_sensors.yaml”, I’ve labeled them appropriately and I’ve added the “Calendar - Populate Trash Calendar” script correctly from the UI (at least it doesn’t give me syntax errors). But when I run it from the UI to create the events in the calendar I get the error “Failed to perform action script/calendar_populate_trash_calendar. AttributeError: ‘NoneType’ object has no attribute 'tzinfo’” (translated from Spanish). What could be happening? I appreciate your help in advance.

Since you have already double checked that all the entity IDs match… I would suggest copying the entire template and pasting it into the Template editor, it may give you a more detailed error message.

That “NoneType” error suggests that the variable holiday may be empty… Did you make sure that the label you used in the frontend matches the one being use in the definition of holiday?

Thanks again for your quick reply. What do you mean by “all the entity IDs match”, the unique_id of each sensor? I have certainly changed some as I have created new sensors adapted to the holidays in Spain, but the sensors are created fine (I have used “generate UUID” from VStudio Code). The only thing I see is that their states are dates already past 2024 (there are no holidays left in 2024 to be able to check if it creates future events, I will wait until 2025). On the other hand, if I put the template that creates these sensors in the template editor, everything is displayed correctly (the states are the expected dates, but from the current year, already past and “days_until” shows what is expected according to the formula (the days that have passed plus 365). At the end it tells me “This template is updated at the beginning of every minute”, although the trigger is fired at “00:01:00”, which is not the same.
Finally, the tag defined in my frontend matches the one I put in the script: “Festivo”