Full-featured scheduling based on cron

Ever wanted to have an automation run on:

  • a specific day like someone’s birthday or a fixed holiday?
  • a floating holiday like Thanksgiving (USA)?
  • the last day of every month?
  • the first Monday but only in June and July?

You can easily do this with cron.

This is a Feature Request to provide scheduling in cron format (the Quartz version of cron).

Cron uses a compact expression to define simple or complex schedules. In the Quartz version of cron, the expression is composed of seven parameters, from second to year.

 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ second (0-59)
 β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ minute (0-59)
 β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ hour (0-23)
 β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ day of the month (1-31)
 β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ month (1-12 or JAN-DEC)
 β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ day of the week (1-7 or SUN-SAT)
 β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ year (optional)
 β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
 β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
 * * * * * * *

For example, the following expression means to trigger on December 25th at 7:15:00 for any year:
0 15 7 25 DEC ? *

Thanksgiving Day (USA) is the fourth Thursday in November. Here’s the expression to trigger on Thanksgiving at 18:45:00 for any year:
0 45 18 ? NOV 5#4 *

Trigger every Monday, Wednesday, and Friday at 6:00:00, 12:00:00, and 18:00:00 from January to March only in 2019.
0 0 6,12,18 ? JAN,FEB,MAR MON,WED,FRI 2019

At noon on the last weekday of every month.
0 0 12 LW * ?

Creating these expressions is simplified through the use of an expression generator like this one:
https://www.freeformatter.com/cron-expression-generator-quartz.html

This Feature Request could either be a completely new cron component or an enhancement to the existing time component.

As a new cron component:

  # compact format
  trigger:
    platform: cron
    at: "0 45 18 ? NOV 5#4 *"

  # verbose format
  trigger:
    platform: cron
      - second: 0
      - minute: 45
      - hour: 18
      - dom: '?'
      - month: 'NOV'
      - dow: '5#4'
      - year: '*'

Alternately, as an enhancement to the existing time component:

  # compact format
  trigger:
    platform: time
    style: cron
    at: "0 45 18 ? NOV 5#4 *"

  # verbose format
  trigger:
    platform: time
    style: cron
      - second: 0
      - minute: 45
      - hour: 18
      - dom: '?'
      - month: 'NOV'
      - dow: '5#4'
      - year: '*'

I’m not proficient with python but a little research suggests there are no python libraries for the Quartz scheduler (which is written in Java). However, on PyPi I found python-crontab. It appears to emulate the classic Unix cron so it lacks some features found in Quartz cron.

For example, it doesn’t support second and year and refers to Sun-Sat as 0-6 (as opposed to 1-7). If the use of python-crontab makes it easier to implement this Feature Request, the loss of second and year is an acceptable compromise.

python-crontab’s expression format using five parameters from minutes to day of the week:

 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ minute (0-59)
 β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ hour (0-23)
 β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ day of the month (1-31)
 β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ month (1-12 or JAN-DEC)
 β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ day of the week (0-6 or SUN-SAT)
 β”‚ β”‚ β”‚ β”‚ β”‚
 β”‚ β”‚ β”‚ β”‚ β”‚
 β”‚ β”‚ β”‚ β”‚ β”‚
 * * * * *

I’d like cron notation as welll in the time pattern trigger.

+1

The current pattern syntax could be easily improved. It is currently too close to Cron syntax, i was surprise not to be able to use it. It’s frustrating and maybe confusing.

This feature will provide more flexibility in triggers. The documentation could refer to the Cron documentation. A simple search with your favourite search engine could help you to find the right syntax. It could also simplify implementation in the core, just by using Cron directly.

This feature will massively reduce complexity in my automation time pattern triggers.

All of these triggers can be created in the local calendar.

Or with templates creating a sensor that holds the date.

Except for this one:

I’m not going to waste time and energy to prove you wrong but I believe it can be done.

Just a simple pseudo;

Now() replace month +1 and day = 1.
Then while %w >=5 remove one day from the datetime.
Then you should get the last weekday

@harac

It’s important to keep in mind that I submitted this Feature Request over 4 years ago. Since then, the Local Calendar integration (as mentioned by tom_l) provides most of the scheduling flexibility provided by cron (although perhaps not as concisely but that’s probably unimportant to many users). Cron still offers a few things that Local Calendar cannot but, arguably, they’re only of use to a minority of users.

FWIW, recently a volunteer software developer submitted a Pull Request (PR), in Home Assistant’s Core repository, to add time ranges to the Time Pattern Trigger. I suggested they consider adding it to the Time Condition so that it could benefit many other triggers. Ultimately, the PR was closed by a member of the development team who suggested the developer consider creating a cron trigger. I have no idea if the developer will do that or not.

1 Like

was bored

{% set t = now() %}
{% set nt = t.replace(day= 1, month=t.month + 1 if t.month < 12 else 1, year=t.year if t.month < 12 else t.year+1) %}
{% set d = (nt - timedelta(days=1)) %}
{% if d.weekday() < 5 %}
  {{ d.date() }} 
{% else %}
  {{ (d - timedelta(d.weekday() - 4)).date() }}
{% endif %}

if you want it at noon, you can just use this as a condition. You could add to this pretty easily to get it to just trigger at noon too using today_at or .time().

2 Likes

Using local calendar seems not suitable for my case. It seems overly complex to create numerous event in the local calendar. Or i will need to be able to create events based on a time pattern :thinking:
The repeat config of local calendar event is too restrictive (dayly, weekly, monthly, yearly).

Thank you for your lovely answer.
This solution seems overly complex.

As i mention in my previous message the current pattern syntax is quitte similar to Cron syntax. It is too bad to not use it (and confusing).

My man, I was replying to Tom I :wink: I wasn’t posting an answer to refute your request.

As I said before just post your problem instead of saying it’s so complex.
I doubt Cron or time pattern is needed.

Oh sorry, i got to it too fast.
Sorry

Always interesting to meet new community members who find Local Calendar and templating β€œoverly complex” to use in comparison to cron’s terse syntax.

3 posts were split to a new topic: Retrieve values from electrical power sensors by sending zigbee command

My point of vue.
I first thought this time pattern was Cron syntax because of their similarities.

I think it is too bad not to use Cron syntax, so close to.
It could improve this feature.
Cron syntax could also easily keep backward compatibility with previous time pattern config, due to their similarities.

That’s good because I was replying to my calendar trigger comment, not yours.