Skip to content

Instantly share code, notes, and snippets.

@bruxy70
Last active January 8, 2024 11:45
Show Gist options
  • Save bruxy70/b55acd9d69de4b8d8880f63e6dcb44cd to your computer and use it in GitHub Desktop.
Save bruxy70/b55acd9d69de4b8d8880f63e6dcb44cd to your computer and use it in GitHub Desktop.
blueprint:
name: Create Calendar Events with Offset Holidays in Week
description: Copy Events (in the next 365 days) from one local calendar to another. Look
in the holidays calendar and shift events for each public holiday in the week
before the event.
domain: script
source_url: https://gist.github.com/bruxy70/b55acd9d69de4b8d8880f63e6dcb44cd
input: {}
fields:
source_calendar:
name: Source calendar
description: Calendar with the events to be copied from
required: true
selector:
entity:
filter:
integration: local_calendar
destination_calendar:
name: Destination calendar
description: Calendar for the events to be copied to
required: true
selector:
entity:
filter:
integration: local_calendar
public_holidays:
name: Public Holidays
description: Calendar with the public holidays to be avoided
required: true
selector:
entity:
filter:
integration: holidays
sequence:
- service: calendar.get_events
data:
duration:
days: 365
target:
entity_id: '{{ source_calendar }}'
response_variable: source
- service: calendar.get_events
data:
duration:
days: 365
target:
entity_id: '{{ destination_calendar }}'
response_variable: destination
- service: calendar.get_events
data:
duration:
days: 365
target:
entity_id: '{{ public_holidays }}'
response_variable: holidays
- variables:
holiday_dates: |-
{%- set ns = namespace(dates={}) %}
{%- if holidays[public_holidays]["events"] %}
{%- for event in holidays[public_holidays]["events"] %}
{%- set ns.dates = dict(ns.dates, **{event.start:event.summary}) %}
{%- endfor %}
{%- endif %}
{{ ns.dates}}
destination_dates: |-
{%- set ns = namespace(dates={}) %}
{%- if destination[destination_calendar]["events"]%}
{%- for event in destination[destination_calendar]["events"] %}
{%- set ns.dates = dict(ns.dates, **{event.start:event.summary}) %}
{%- endfor %}
{%- endif %}
{{ ns.dates}}
- repeat:
for_each: '{{ source[source_calendar]["events"] }}'
sequence:
- variables:
offset: >-
{%- set ns = namespace(offset=0,in_week=False,found=False) %}
{%- set collection_date = strptime(repeat.item.start,"%Y-%m-%d").date() %}
{%- for i in range(collection_date.weekday()+1) %}
{%- set d = ( collection_date + timedelta( days=-i) ).isoformat() %}
{%- if d in holiday_dates %}
{%- set ns.in_week = true %}
{%- set ns.offset = ns.offset + 1 %}
{%- endif %}
{%- endfor %}
{%- if ns.in_week %}
{# Increase offset until we find a date that is not public holiday #}
{%- for _ in range(7) if not ns.found %}
{%- set start = strptime(repeat.item.start,"%Y-%m-%d").date() %}
{%- set d = ( start + timedelta( days=ns.offset) ).isoformat() %}
{%- if d in holiday_dates %}
{%- set ns.offset = ns.offset + 1 %}
{% else %}
{%- set ns.found = true %}
{%- endif %}
{% endfor %}
{%- endif %}
{{ ns.offset }}
start_date: >-
{%- set start = strptime(repeat.item.start,"%Y-%m-%d").date() %}
{{ (start + timedelta(days=offset)).isoformat() }}
end_date: >-
{%- set end = strptime(repeat.item.end,"%Y-%m-%d").date() %}
{{ (end + timedelta(days=offset)).isoformat() }}
summary: "{{ repeat.item.summary }}"
- if:
- condition: template
value_template: "{{ start_date not in destination_dates }}"
then:
- service: calendar.create_event
data:
summary: "{{ summary }}"
start_date: "{{ start_date }}"
end_date: " {{ end_date }}"
target:
entity_id: "{{ destination_calendar }}"
mode: single
icon: mdi:calendar-blank-multiple
@lambros414
Copy link

lambros414 commented Jan 3, 2024

Okay. sorry, totally fixed. I learned that I was nesting templates.

the proper solutions for above is to do:

{%- for event in holidays[public_holidays]["events"] %}

{%- for event in destination[destination_calendar]["events"] %}

and

for_each: '{{ source[source_calendar]["events"] }}'

The full code which appears to be working now is below:
template above

`

blueprint:
  name: Create Calendar Events with Offset Holidays in Week
  description: Copy Events (in the next 365 days) from one local calendar to another.  Look
    in the holidays calendar and shift events for each public holiday  in the week
    before the event.
  domain: script
  source_url: https://gist.github.com/bruxy70/b55acd9d69de4b8d8880f63e6dcb44cd
  input: {}
fields:
  source_calendar:
    name: Source calendar
    description: Calendar with the events to be copied from
    required: true
    selector:
      entity:
        filter:
          integration: local_calendar
  destination_calendar:
    name: Destination calendar
    description: Calendar for the events to be copied to
    required: true
    selector:
      entity:
        filter:
          integration: local_calendar
  public_holidays:
    name: Public Holidays
    description: Calendar with the public holidays to be avoided
    required: true
    selector:
      entity:
        filter:
          integration: holidays
sequence:
- service: calendar.get_events
  data:
    duration:
      days: 365
  target:
    entity_id: '{{ source_calendar }}'
  response_variable: source
- service: calendar.get_events
  data:
    duration:
      days: 365
  target:
    entity_id: '{{ destination_calendar }}'
  response_variable: destination
- service: calendar.get_events
  data:
    duration:
      days: 365
  target:
    entity_id: '{{ public_holidays }}'
  response_variable: holidays
- variables:
    holiday_dates: |-
      {%- set ns = namespace(dates={}) %}
      {%- if holidays[public_holidays]["events"] %}
        {%- for event in holidays[public_holidays]["events"] %}
          {%- set ns.dates = dict(ns.dates, **{event.start:event.summary}) %}
        {%- endfor %}
      {%- endif %}
      {{ ns.dates}}
    destination_dates: |-
      {%- set ns = namespace(dates={}) %}
      {%- if destination[destination_calendar]["events"]%}
        {%- for event in destination[destination_calendar]["events"] %}
          {%- set ns.dates = dict(ns.dates, **{event.start:event.summary}) %}
        {%- endfor %}
      {%- endif %}
      {{ ns.dates}}
- repeat:
    for_each: '{{ source[source_calendar]["events"] }}'
    sequence:
        - variables:
            offset: >-
              {%- set ns = namespace(offset=0,in_week=False,found=False) %}
              {%- set collection_date = strptime(repeat.item.start,"%Y-%m-%d").date() %}
              {%- for i in range(collection_date.weekday()+1) %}
                {%- set d = ( collection_date + timedelta( days=-i) ).isoformat() %}
                {%- if d in holiday_dates %}
                  {%- set ns.in_week = true %}
                  {%- set ns.offset = ns.offset + 1 %}
                {%- endif %}
              {%- endfor %}
              {%- if ns.in_week %}
                {# Increase offset until we find a date that is not public holiday #}
                {%- for _ in range(7) if not ns.found %}
                  {%- set start = strptime(repeat.item.start,"%Y-%m-%d").date() %}
                  {%- set d = ( start + timedelta( days=ns.offset) ).isoformat() %}
                  {%- if d in holiday_dates %}
                    {%- set ns.offset = ns.offset + 1 %}
                  {% else %}
                    {%- set ns.found = true %}
                  {%- endif %}
                {% endfor %}               
              {%- endif %} 
              {{ ns.offset }}
            start_date: >-
              {%- set start = strptime(repeat.item.start,"%Y-%m-%d").date() %}
              {{ (start + timedelta(days=offset)).isoformat() }}
            end_date: >-
              {%- set end = strptime(repeat.item.end,"%Y-%m-%d").date() %}
              {{ (end + timedelta(days=offset)).isoformat() }}
            summary: "{{ repeat.item.summary }}"
        - if:
            - condition: template
              value_template: "{{ start_date not in destination_dates }}"
          then:
            - service: calendar.create_event
              data:
                summary: "{{ summary }}"
                start_date: "{{ start_date }}"
                end_date: " {{ end_date }}"
              target:
                entity_id: "{{ destination_calendar }}"
mode: single
icon: mdi:calendar-blank-multiple

`

@bruxy70
Copy link
Author

bruxy70 commented Jan 8, 2024

Thanks for this contribution, I have updated the blueprint to this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment