Local Calendar - recurring event exclude months

I don’t believe it’s current possible to exclude months for recurring events in local calendar which is needed for my garden waste events. My garden waste is picked up every two weeks April to September. Is there anyway to do this now or workaround or can this be considered as a feature request?

Thanks

It is possible to programmatically populate calendar event like this using an annual automation. But it requires a defined logic for which week the pattern starts on in order to build a template that drives a Repeat for Each action. If you can figure out the starting week and provide the day of the week you want the event on we may be able to help you put together the automation.

1 Like

I did consider if it was possible to populate events at the start of each year but the week number for each year could be different so not sure if it’s possible? For example my next garden waste collection is the 29th August and it’s every two weeks after that. When October commences garden waste collections stop and resume in April however it still falls on the 2nd week so for me my last collection will be 26th September and first collection next year will be 9th April

This is a rough draft… but it seems to be working.

Macro Template
{% macro limited_biweekly(start_month, end_month, event_dow, offset=0) %}
{%- set end_month_str = end_month|string if end_month > 9 else '0'~end_month|string %}
{%- set start_month_str = start_month|string if start_month > 9 else '0'~start_month|string %}
{% set last_day = now().replace(month= end_month + 1, day=1) - timedelta(days=1) %}
{%- set end_day = (last_day).day %} 

{%- set bi_event = namespace(dates=[]) %}
{%- set year = today_at().year %}
{%- set first_of_month = (year~"-"~start_month_str~"-01") | as_datetime | as_local%}
{%- set inter_first = first_of_month + 
timedelta(days = event_dow - first_of_month.weekday()) %}
{%- set first_weekday = inter_first if inter_first.strftime('%m') == start_month_str
else inter_first + timedelta(days=7) %}

{% for i in range(0, ((last_day - first_of_month).days // 7) + 1 )%}
  {%- set bi_event.dates = bi_event.dates + 
  [first_weekday + timedelta(days=7 * offset)+ timedelta(days=14 * i)] %}
{%- endfor %}
 
{%- set bi_event.dates = bi_event.dates 
| reject('<', first_of_month) | reject('>', last_day) | list %}

{{- bi_event.dates | map('string')
| map('truncate', 14, False, '') | unique | list }}
{% endmacro %}
Script

Make sure to update the date_list variable to reflect where you store your template macros.

alias: Calendar - Populate Limited Biweekly Event
description: ""
fields:
  start_month:
    name: Start Month
    description: Month in which to start adding events.
    example: 4
    required: true
    selector:
      select:
        options:
          - label: January
            value: "1"
          - label: February
            value: "2"
          - label: March
            value: "3"
          - label: April
            value: "4"
          - label: May
            value: "5"
          - label: June
            value: "6"
          - label: July
            value: "7"
          - label: August
            value: "8"
          - label: September
            value: "9"
          - label: October
            value: "10"
          - label: November
            value: "11"
          - label: December
            value: "12"
  end_month:
    name: End Month
    description: The last month to populate events in.
    example: 10
    required: true
    selector:
      select:
        options:
          - label: January
            value: "1"
          - label: February
            value: "2"
          - label: March
            value: "3"
          - label: April
            value: "4"
          - label: May
            value: "5"
          - label: June
            value: "6"
          - label: July
            value: "7"
          - label: August
            value: "8"
          - label: September
            value: "9"
          - label: October
            value: "10"
          - label: November
            value: "11"
          - label: December
            value: "12"
  weekday:
    name: Weekday Index
    description: The index of the day of the week on which the events occur (Monday = 0)
    example: 1
    required: true
    selector:
      select:
        options:
          - label: Sunday
            value: "6"
          - label: Monday
            value: "0"
          - label: Tuesday
            value: "1"
          - label: Wednesday
            value: "2"
          - label: Thursday
            value: "3"
          - label: Friday
            value: "4"
          - label: Saturday
            value: "5"
  week_offset:
    name: Offset
    description: >-
      The number of weeks from the first week of the month to offset the start.
    example: 0
    required: true
    selector:
      number:
        min: 0
        max: 3
  calendar:
    name: Calendar
    description: The calendar entity to post the events to.
    example: calendar.chores
    required: true
    selector:
      entity:
        multiple: false
        filter:
          - domain: calendar
  summary:
    name: Title
    description: The title/summary of the calendar event.
    example: Trash Night
    required: true
    selector:
      text: null
sequence:
  - variables:
      date_list: >
        {% from 'tools.jinja' import limited_biweekly %} 
        {{limited_biweekly(start_month|int,end_month|int,weekday|int,week_offset)}}
  - repeat:
      for_each: "{{date_list}}"
      sequence:
        - service: calendar.list_events
          data:
            start_date_time: "{{ repeat.item|string~'T00:00:00.000Z'}}"
            duration:
              hours: 24
          target:
            entity_id: "{{ calendar }}"
          response_variable: agenda
        - if:
            - condition: template
              value_template: |-
                {{ not summary in agenda.events | map(attribute='summary') | list }}
          then:
            - service: calendar.create_event
              data:
                summary: "{{ summary }}"
                start_date: "{{ repeat.item|string }}"
                end_date: >
                  {% set new = repeat.item|string|as_datetime + timedelta(days=1) %}
                  {{ new.date()|string }}
              target:
                entity_id: "{{ calendar }}"
        - delay: 1
mode: single

1 Like

That works for me and populates correctly so I can call the script at the start of year to populate my calendar. Thank you! I’ll have to have a play and see if there is a way I can automatically calculate the offset so it runs without me having to remember to run it