# All about CRON

## What about a CRON?

CRON strings are a concise way of telling the application when to schedule or run something. Perigee uses CRON string data throughout for advanced process scheduling and events.&#x20;

### CRON Data Explanation

Most CRON strings contain five bits. Perigee's CRON can contain 6 if you use the optional seconds bit.

```
Second   Minute      Hour      Day      Month      Day-Of-Week
   *        *         *         *         *            *
```

* The **ASTERISK** character means "All Available Values"
  * For hour, this is 0-23
  * For Minute, this is 0-59
  * For Day this is 1-31
  * For Month this is 1-12
  * For Day-Of-Week this is 0-6 (Sunday being 0)
* The **COMMA** character is a list of values
  * If the Month bit is **`0,1,2`** - Then the CRON is only run in Jan, Feb and March.
* The **DASH** character means a range from a-z.
  * If the day bit is **`0-6`** - Then the CRON is only run the first 7 days of the month
* The **SLASH** character is a divider of all available values.
  * If the second bit is **`*/5`** - Then the CRON is executed on every fifth second.
* There are several special characters that can only be used in certain situations.&#x20;
  * The **F** character is for FIRST OF:
    * This can be used in the Day or Day-Of-Week bits
    * In the day bit, **`F`** - The CRON would run the first day of the month
  * The **L** character is for LAST OF:
    * This can be used in the Day or Day-Of-Week bits
    * In the day bit, **`L-2`** - The CRON would run the second from last day of the month
  * The **#** is for day-of-week selector
    * This is only used in the Day-Of-Week bit:
    * **`0#2`** would be the second Sunday (0 Sunday #2)
    * **`1#3`** would be the third Monday (1 Monday #3)

## Examples

### How would I run a CRON every morning at 5AM ?

* Let's leave out the seconds since we don't need that here.&#x20;
* If we don't specify 0 in the minute bit the CRON it will run every minute of 5AM.
* 5AM is 5 in the hour bit.
* The key request is "every day", so let's set the day bit to an asterisk.
* Every other

```
0 5 * * *
```

### How would I run a CRON at 1AM on the last Friday of every month?

* This is where that special L character comes into play.
  * Day-Of-Week starts as 0 Sunday, so Friday would be 5.
  * Asking for the last friday of the month would be L5 in day-of-week bit.
* If we don't specify 0 in the minute bit the CRON it will run every minute of 1AM.
* 1AM in the hour bit is 1
* Asterisks for the other fields

```
0 1 * * L5
```

### How would I run a CRON at 1AM on the second to last day of the month?

* This is where that special L character comes into play again.
  * Asking for the second to last day of of the month would be L-2 in day bit.
* If we don't specify 0 in the minute bit the CRON it will run every minute of 1AM.
* 1AM is the hour bit is 1
* Asterisks for the other bits&#x20;

```
0 1 L-2 * *
```

## The SDK

#### Parse

Call Parse on any CRON string. It will detect if seconds are present.

```csharp
var cparsed = Cron.Parse("0 1 * * 0#1");
```

#### Occurrence

Get the next occurrence from a given date or supply a different time zone to find the next occurrence in that time zone.

```csharp
var nOcc = cparsed.GetNextOccurrence(DateTimeOffset.Now);

//You can also supply a timezone:
var nOcc = cparsed.GetNextOccurrence(DateTimeOffset.Now, TimeZoneInfo.Utc);
```

#### Print info

You can use that parsed CRON to display info about it.

```csharp
Console.WriteLine(cparsed.ToString());
//Prints: on minute 0 on hour 1 on the 1st Sunday
```

#### Inverse Period

The only other method you may care about is the **`InversePeriod`**. **`InversePeriod`** is interesting as it takes the CRON string and determines how consecutively it runs.

```csharp
var inv = Cron.Parse("* 1-2 * * *").GetInversePeriod(DateTimeOffset.Now);
Console.WriteLine($"From {inv.Item1:G} to {inv.Item2:G}");

//Prints: From 1/1/2023 1:00:00 AM to 1/1/2023 2:59:00 AM
```

Notice how this CRON would run from 1AM consistently at every interval (minute) inclusively to 2:59AM? This method is an interesting way to use CRON data to specify ranges of time.

## CRON in Perigee

There are bunch of ways to use CRON strings in Perigee. Let's take a look at a few:

#### Agents

[SyncAgents](/core-modules/event-sources/scheduled-logic/sync-agent.md) use CRON strings to determine when to run, and even when to create blackout periods. You can see more in the linked section. Here's a quick preview!

{% code lineNumbers="true" %}

```csharp
taskConfig.AddAgent("DailySync", "DailySync", "DailyDB", 
new SyncAgentSourceMemory("SA.json"), AgentRunCondition.RunIfPastDue,

(configAgent) => configAgent.SetSyncLimitPerDay(2).SetSync(null, "55 6 * * *"),

(ct, l, executeHandler) => 
    DailySync.sync(taskConfig, taskConfig.CTS.Token, log, executeHandler, "DailyDB"),

(ct, l, treeHandler) => { },

TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(10), false)
    .LinkToConfig("Agents:DailySyncEnabled");
```

{% endcode %}

#### BlockUntil&#x20;

This is a handy way of creating an awaitable task, or thread blocking mechanism using a CRON string.

```csharp
//Async wait until the 0th second of every 5th minute
await PerigeeUtil.BlockUntil("0 */5 * * * *");

//Or for non async methods
PerigeeUtil.BlockUntil("0 */5 * * * *").GetAwaiter().GetResult();
```

#### Methods using CRON

As part of the core set of events in Perigee, you can easily add CRON methods.

```csharp
PerigeeApplication.ApplicationNoInit("Crons", (c) =>
{
    c.AddCRON("CronMethod", "0 */5 * * * *", (ct, l) => {
        //Run's every 5 minutes at second 0
    });

});
```

## CRON Testing Resources

#### A method to parse and print

A handy little method to print the definition of a CRON string, as well as print the next occurrence:

```csharp
void PrintCRON(string inputStr)
{
    Console.WriteLine(inputStr);
    var cparsed = Cron.Parse(inputStr);
    Console.WriteLine(cparsed.ToString());
    var nOcc = cparsed.GetNextOccurrence(DateTimeOffset.Now);
    Console.WriteLine(nOcc.Value.ToString("G") + Environment.NewLine);
}
```

#### A site to test CRON data

This is an amazing site to visually and instantly see the results of a CRON.&#x20;

{% hint style="warning" %}
FYI, They don't supports seconds or the special character options :thumbsup:
{% endhint %}

{% embed url="<https://crontab.guru>" %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.perigee.software/perigee-and-beyond/all-about-cron.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
