Edit Calendar Entry

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 }}