Schedule Based On Day of Month, But Not Date

What do you mean by “schedule an event”?

Trigger an automation?

trigger:
  - platform: template
    value_template: |
      {% set dt = today_at() %}
      {{ (dt.month == 3) and (8 <= dt.day <= 14) 
      and (dt.isoweekday() == 7) }}

Automate creating a Calendar event that happens on that day?

This is much easier done using the Easy Time Macro: month_week_day module

service: calendar.create_event
data:
  summary: 2nd Sunday in March
  start_date: |
    {% from 'easy_time.jinja' import month_week_day %}
    {{ month_week_day(3, 2, 7)[:10]}}
  end_date: |
    {% from 'easy_time.jinja' import month_week_day %}
    {{ month_week_day(3, 2, 1)[:10]}}
target:
  entity_id: calendar.example

If you’re actually looking for DST use the next_dst function:

{% from 'easy_time.jinja' import next_dst %}
{{ next_dst() }}

I want to turn on the lights at a certain time tarting on the second Sunday of March, and ending on the first Sunday in November. I then want them to turn on at a different time between the first Sunday in November and the second Sunday in March. This year the second Sunday in March is the 10th, but it won’t be the 10th next year, so I cannot set it by numerical date.

There are multiple ways to do that… here’s one that can be done without extra helper entities:

trigger:
  - alias: March to November
    platform: time
    at: "07:30:30"
    id: '1'
  - alias: November to March
    platform: time
    at: "08:30:30"
    id: '0'
condition:
  - condition: template
    value_template: "{{ now().timetuple().tm_isdst == trigger.id | int  }}"
action:

EDIT: Fixed string/int issue in condition

2 Likes

Tip

I’m mentioning this to you only because, as an experienced user, you might find this handy in the future (you may already be aware of it). For beginners, it might be confusing.

The value of the first trigger’s id is automatically 0 (as a string). The next trigger’s id is 1 and so on. So even if you don’t explicitly specify a value for id, it will have a default value representing its position in the list of triggers (and it will be the same value as its idx property).

If you swap the order of the two triggers in your example, the id value for the “November to March” Time Trigger will automatically be 0 so you don’t have to explicitly indicate id: 0 and can safely remove that line.

1 Like

if you’re actually looking for daylight savings time change dates, you should definitely do what @Didgeridrew said.

if you need to other Nth day of the month, look at the rest of what timetuple() has to offer: timetuple() Function Of Datetime.date Class In Python - GeeksforGeeks

to get the Nth occurance of a day in the month, this should do it for you:

{{ now().timetuple().tm_wday == DOW and 
  now().timetuple().tm_mday % 7 == (Nth - 1) }}

where DOW is the day of the week (0 == monday, 6 == sunday)
and Nth is the Nth week of the month.

1 Like

I am somewhat familiar with c++, but am fairly new to home assistant, and a complete novice with yaml. I do most things via the UI. Would this solution be creating custom triggers that I would then use in the automations section of the UI

yes, choose template in the ui.
you can choose templates for triggers or condition.

1 Like

I will definitely look into this once u better understand the basics of all of this as I would eventually like to have finer control over when the tiger basketball then just the beginning of the month.

Would I place the code in configuration.yaml, or is there a way to better organize everything? I would ideally like to have a lights.yaml, triggers.yaml, etc… if that’s a thing. If it is, would I still need some code in configuration.yaml to call the others?

If you need a primer on transcribing YAML automation configuration to the UI Editor there is a slightly dated video available here.

No, the most recent post I made uses 2 normal Time triggers with assigned IDs (this is available in the drop down menu for the trigger under “Edit ID”:

The condition is a Template condition, also 100% do-able in the UI editor.

1 Like

no, you put it in the automation page… if you want to trigger on it, put it in trigger. if you want it to be a condition, put it on the condition.

so this:

triggers at 11am if it’s the 2nd sunday of the month.
home assistant will then generate the full yaml and put it in the automation.yaml page or you (or the script.yaml if you’re doing a script).

if you’re just learning yaml to start, i would encourage you to use the ui, let it build the yaml. then at the end, go look and learn from the yaml it generated.

start by doing only the yaml and templating that you must do… let the ui guide you for the rest.

1 Like

Thanks everyone! This has been extremely helpful. I appreciate your time on this! :grin::heart:

I would like to try and use a combination of what you two are saying, and yes, this is for daylight savings time. Is there anyway to have the lights turn-on on the second Sunday of March at 2000 hrs and continue to do so every day until the first Sunday of November when they will turn on at 1800 hrs until the second Sunday of March the next year?

Also I’m getting this error when trying to create the automation.


The trigger ID’s need to be ‘0’ and ‘1’, as shown in my post above, for the condition to work.

1 Like

Thank you!

Credit for solution goes to Didgeridrew and armedad.

For anyone that scrolls this far, the solution is two fold:

1 Like

Sorry to reopen this post but I have a qustion about the usage and this seems to be the only thread related to this topic.

So my goal is to create all-day calendar entries for every third friday of a month because this is when the paper trash is collected. I have made a script to automatically create calendar entries. For each month there is an action that looks like this:

action: calendar.create_event
data:
  summary: Papiermüll
  start_date: |
    {% from 'easy_time.jinja' import month_week_day %}
    {{ month_week_day(XX, 3, 5)[:10]}}
  end_date: |
    {% from 'easy_time.jinja' import month_week_day %}
    {{ month_week_day(XX, 3, 6)[:10]}}
target:
  entity_id: calendar.test

where XX is a number between 1-12 for each month.

This works well for every month - except for June 2024. June 1st is a saturday. So time.jinja counts (6, 3, 5) as the 21st of June but (6, 3, 6) as the 15th resulting in a negative duration and thus a failure to create the event.
Technically this is correct behaviour as they are both the third occurencies of given weekday but it is not a desired result.

So my question is: Is there any way to set the end date to “one day after the start date” or something? - Or is there a better way to do this?

Also: could someone kindly explain what “[:10]” does? I can’t find anything about it in the documentation, I just know the script doesn’t work without it…

I know this date is in the past and doesn’t matter anymore specifically, but I would like a working universal solution that I don’t have to check on every other year.

ChatGPT had this solution, feels like this is it:

action: calendar.create_event
data:
  summary: Papierabfuhr
  start_date: >
    {% from 'easy_time.jinja' import month_week_day %}
    {{ month_week_day(XX, 3, 5)[:10] }}
  end_date: >
    {% from 'easy_time.jinja' import month_week_day %}
    {{ (as_timestamp(month_week_day(XX, 3, 5)[:10]) + 86400) | timestamp_custom("%Y-%m-%d") }}
target:
  entity_id: calendar.test

Do you actually need a script? Your problem is categorically different than the original post… OP wanted an annual repeat that accounted for the Month, Week index, and Day of the week.
The Repeat Monthy option in the “Add Event” dialog can handle what you are trying to do, and have it repeat forever:

This is one way to perform slicing based on index number. This is a basic method used in Python and, as such, is considered outside the scope of Home Assistant documentation. In this case it selects the first 10 elements of the datetime string so it returns some like 2024-03-10 instead of something like 2024-03-10T00:00:00-05:00. The calendar.create_event has been updated since the start of this thread to allow datetime date objects. Slicing will still work, but it isn’t the only option.

ChatGPT is a bullshit engine… and that’s exactly what it has given you.

action: calendar.create_event
data:
  summary: Papierabfuhr
  start_date: >
    {% from 'easy_time.jinja' import month_week_day %}
    {{ month_week_day(month, 3, 5)[:10] }}
  end_date: >
    {% from 'easy_time.jinja' import month_week_day %}
    {{ (month_week_day(month, 3, 5) | as_datetime | as_local + timedelta(days=1)).date() }}
target:
  entity_id: calendar.test