Help needed with calendar.create event

hi team!

I’m trying to build a little system that would create an event in the calendar, however I can’t seem to parse date correctly. Can someone spot where the issue lies??

This is my automation:

alias: Handle Time Off Approval
description: ""
triggers:
  - event_type: mobile_app_notification_action
    event_data:
      action: APPROVE_TIME_OFF
    trigger: event
actions:
  - variables:
      balance: "{{ states('input_number.remaining_balance') | float }}"
      start: "{{ states('input_datetime.start_date') | as_datetime }}"
      end: "{{ states('input_datetime.end_date') | as_datetime }}"
      duration: "{{ states('input_number.last_time_off_duration') | float }}"
      new_balance: "{{ balance - duration }}"
  - target:
      entity_id: input_number.remaining_balance
    data:
      value: "{{ new_balance }}"
    action: input_number.set_value
  - data:
      title: Time Off Approved
      message: "✅ Request approved. Remaining balance: {{ new_balance }} days"
    action: notify.mobile_app_asus_i005da
  - action: calendar.create_event
    metadata: {}
    data:
      start_date: "{{ start.strftime('%Y-%m-%d') }}"
      end_date: "{{ (end + timedelta(days=1)).strftime('%Y-%m-%d') }}"
      summary: Aupair - Time Off
    target:
      entity_id:
        - calendar.olamike
        - calendar.gezin
mode: single

And this is the error I am receiving:
Error: Error rendering data template: UndefinedError: ‘str object’ has no attribute ‘strftime’

It shows up on the last step of the automation, so it’s tied to the calendar event.

What do the state values of these two entities contain?

input_datetime.start_date
input_datetime.end_date

Do they contain just the date (2025-04-01) or the date and time (2025-04-01 08:15)?


Assuming it contains both date and time, you can do this:

start_date: "{{ states('input_datetime.start_date')[:10] }}"

If it simply contains the date then you can remove the [:10] from the end of the template.

If you get an error for end_date’s template, replace the template’s end variable with states('input_datetime.end_date') | as_datetime

In other words, don’t use script variables to store datetime objects.

So I had both helpers to contain only date. I’ve updated them to contain date and time now and your solution works… however… the event get’s created only for one day (start day) or not at all (if duration is longer than 1 day) and there is a duplicate as well. I am starting to think that I should handle this in a script instead. I wonder maybe I should do this as a custom component??? I saw another approach like this to set up sensors fr dates like Today, Tomorrow, day after tomorrow… and it was basically what I need, add a day to the date.

Post the revised version of the templates you’re using for start_date and end_date.

So I played a bit more ad I decided to dump the idea of using end date as apparently it’s super hard to increment date in automations and I switched to start_date plus in: days: number, but I am getting strange error even though values are populated:

Error: must contain at most one of start_date, start_date_time, in.
Result:
params:
  domain: calendar
  service: create_event
  service_data:
    start_date: '2025-03-27'
    in:
      days: 3
    summary: Aupair - Time Off
    entity_id:
      - calendar.olamike
      - calendar.gezin
  target:
    entity_id:
      - calendar.olamike
      - calendar.gezin
running_script: false

ad here’s the updated automation script (i know the end_date is till there, one battle at a time!! :slight_smile: )

alias: Handle Time Off Approval
description: ""
triggers:
  - event_type: mobile_app_notification_action
    event_data:
      action: APPROVE_TIME_OFF
    trigger: event
actions:
  - variables:
      balance: "{{ states('input_number.remaining_balance') | float }}"
      start: "{{ states('input_datetime.start_date')[:10] }}"
      end: "{{ states('input_datetime.end_date') | as_datetime }}"
      duration: "{{ states('input_number.last_time_off_duration') | float }}"
      new_balance: "{{ balance - duration }}"
  - target:
      entity_id: input_number.remaining_balance
    data:
      value: "{{ new_balance }}"
    action: input_number.set_value
  - data:
      title: Time Off Approved
      message: "✅ Request approved. Remaining balance: {{ new_balance }} days {{ end }}"
    action: notify.mobile_app_asus_i005da
  - action: calendar.create_event
    metadata: {}
    data:
      start_date: "{{ start }}"
      in:
        days: "{{ duration }}"
      summary: Aupair - Time Off
    target:
      entity_id:
        - calendar.olamike
        - calendar.gezin
mode: single
alias: Handle Time Off Approval
description: ""
triggers:
  - event_type: mobile_app_notification_action
    event_data:
      action: APPROVE_TIME_OFF
    trigger: event
actions:
  - variables:
      balance: "{{ states('input_number.remaining_balance') | float }}"
      start: "{{ (states('input_datetime.start_date') | as_datetime).date() | string }}"
      end: "{{ (states('input_datetime.end_date') | as_datetime + timedelta(days=1)).date() | string }}"
      duration: "{{ states('input_number.last_time_off_duration') | float }}"
      new_balance: "{{ balance - duration }}"
  - target:
      entity_id: input_number.remaining_balance
    data:
      value: "{{ new_balance }}"
    action: input_number.set_value
  - data:
      title: Time Off Approved
      message: "✅ Request approved. Remaining balance: {{ new_balance }} days"
    action: notify.mobile_app_asus_i005da
  - action: calendar.create_event
    metadata: {}
    data:
      start_date: "{{ start }}"
      end_date: "{{ end }}"
      summary: Aupair - Time Off
    target:
      entity_id:
        - calendar.olamike
        - calendar.gezin
mode: single
1 Like

Oh my gosh! I love you :smiley: This thing was spending sleep from my eyes at nights!

1 Like