How to Specify Time in Cron Considering Year

How do I set up cron to run a file just once at a specific time?

Try this out to execute a command on 30th March 2011 at midnight:

0 0 30 3 ? 2011  /command

WARNING: As noted in comments, the year column is not supported in standard/default implementations of cron. Please refer to TomOnTime answer below, for a proper way to run a script at a specific time in the future in standard implementations of cron.

How can I create Cron Expression which works between particular times

Some things you cannot do in a single expression and you might consider to use two:

# Example of job definition:
# .--------------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
# This runs on 7:30, 7:40, 7:50
30/10 7 * * 1-5 command
# This runs on 8:00, 8:10, 8:20
0-20/10 8 * * 1-5 command

Another way you could attempt this is by using a test.

# Example of job definition:
# .--------------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
*/10 7,8 * * 1-5 testcmd && command

Where testcmd is an executable script that could look like:

#!/usr/bin/env bash
hours=$(date "+%H")
minutes=$(date "+%M")
(( hours == 7 && minutes >= 30)) || (( hours == 8 && minutes <= 20 ))

Other examples of this trick can be found here:

  • Cron expression to run every N minutes
  • How to schedule a Cron job to run 4th week of the year
  • how to set cronjob for 2 days?

CRON job to run on the last day of the month

Possibly the easiest way is to simply do three separate jobs:

55 23 30 4,6,9,11        * myjob.sh
55 23 31 1,3,5,7,8,10,12 * myjob.sh
55 23 28 2 * myjob.sh

That will run on the 28th of February though, even on leap years so, if that's a problem, you'll need to find another way.


However, it's usually both substantially easier and correct to run the job as soon as possible on the first day of each month, with something like:

0 0 1 * * myjob.sh

and modify the script to process the previous month's data.

This removes any hassles you may encounter with figuring out which day is the last of the month, and also ensures that all data for that month is available, assuming you're processing data. Running at five minutes to midnight on the last day of the month may see you missing anything that happens between then and midnight.

This is the usual way to do it anyway, for most end-of-month jobs.


If you still really want to run it on the last day of the month, one option is to simply detect if tomorrow is the first (either as part of your script, or in the crontab itself).

So, something like:

55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh

should be a good start, assuming you have a relatively intelligent date program.

If your date program isn't quite advanced enough to give you relative dates, you can just put together a very simple program to give you tomorrow's day of the month (you don't need the full power of date), such as:

#include <stdio.h>
#include <time.h>

int main (void) {
// Get today, somewhere around midday (no DST issues).

time_t noonish = time (0);
struct tm *localtm = localtime (&noonish);
localtm->tm_hour = 12;

// Add one day (86,400 seconds).

noonish = mktime (localtm) + 86400;
localtm = localtime (&noonish);

// Output just day of month.

printf ("%d\n", localtm->tm_mday);

return 0;
}

and then use (assuming you've called it tomdom for "tomorrow's day of month"):

55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh

Though you may want to consider adding error checking since both time() and mktime() can return -1 if something goes wrong. The code above, for reasons of simplicity, does not take that into account.

How to consider daylight savings time when using cron schedule in Airflow

Starting with Airflow 1.10, time-zone aware DAGs can be defined using time-zone aware datetime objects to specify start_date. For Airflow to schedule DAG runs always at the same time (regardless of a possible daylight-saving-time switch), use cron expressions to specify schedule_interval. To make Airflow schedule DAG runs with fixed intervals (regardless of a possible daylight-saving-time switch), use datetime.timedelta() to specify schedule_interval.

For example, consider the following code that, first, uses a cron expression to schedule two consecutive DAG runs, and then uses a fixed interval to do the same.

import pendulum
from airflow import DAG
from datetime import datetime, timedelta

START_DATE = datetime(
year=2019,
month=10,
day=25,
hour=8,
minute=0,
tzinfo=pendulum.timezone('Europe/Kiev'),
)


def gen_execution_dates(start_date, schedule_interval):
dag = DAG(
dag_id='id', start_date=start_date, schedule_interval=schedule_interval
)
execution_date = dag.start_date
for i in range(1, 3):
execution_date = dag.following_schedule(execution_date)
print(
f'[Run {i}: Execution Date for "{schedule_interval}"]:',
dag.timezone.convert(execution_date),
)


gen_execution_dates(START_DATE, '0 8 * * *')
gen_execution_dates(START_DATE, timedelta(days=1))

Running the code produces the following output:

[Run 1: Execution Date for "0 8 * * *"]: 2019-10-26 08:00:00+03:00
[Run 2: Execution Date for "0 8 * * *"]: 2019-10-27 08:00:00+02:00
[Run 1: Execution Date for "1 day, 0:00:00"]: 2019-10-26 08:00:00+03:00
[Run 2: Execution Date for "1 day, 0:00:00"]: 2019-10-27 07:00:00+02:00

For the zone [Europe/Kiev], the daylight saving time of 2019 ends on 2019-10-27 at 03:00:00+03:00. That is, between Run 1 and Run 2 in our example.

The first two output lines show that for the DAG runs scheduled with a cron expression the first run and second run are both scheduled for 08:00 (although, in different timezones: Eastern European Summer Time (EEST) and Eastern European Time (EET) respectively).

The last two output lines show that for the DAG runs scheduled with a fixed interval the first run is scheduled for 08:00 (EEST), and the second run is scheduled exactly 1 day (24 hours) later, which is at 07:00 (EET) due to the daylight-saving-time switch.

The following figure illustrates the example:

Sample Image

How to run Quarz Cron Job between specific time?

After understanding your requirement clearly, AFAIK, you need two schedulers:

First Scheduler (runs between hours 07:00 to 21:00):

Cron expression should be like 0 3/15 7-20 * * *

0 - seconds

3/15 - runs at 3rd, 18th, 33rd, 48th minutes of each hour

7-20 - starting from 07AM to 08PM (included)

Second Scheduler (runs ONLY at 21:04):

Cron expression should be like 0 4 21 * * * (which runs ONLY at 21:04)

Run cron at a different frequency in specific interval

not easy in a single cron, and that is also hard to read.

multiple jobs may work fine and show much clear

// This will start at 1:10am, and every 30minutes run once.
0+10/30+1-23/2+*+*+?
// This will start at 0:10am, and every 15minutes run once.
0+10/15+0-24/2+*+*+?

you may also consider to void the two job running at the same time.



Related Topics



Leave a reply



Submit