Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@ Each field (except time) supports:
09:00-17:00 * * 1-5; 10:00-16:00 * * 6-12 # Different hours for different months
```

## Overnight Ranges

A time range with the end earlier than the start spans midnight, for example `23:00-02:00`. Each rule is
evaluated against a single calendar day: the `dow`, `dom` and `month` fields are matched against the day
shown on the clock, and the time matches when it is at or after the start, or at or before the end.

With wildcard calendar fields this gives the continuous overnight window every night, which is what
`23:00-07:00 * * *` above describes. With a narrower field it does not. `23:00-02:00 1 * *` selects
Mondays, so it matches Monday 00:00 to 02:00 and Monday 23:00 to midnight, and it does not match
Tuesday 00:30. To express a window running from Monday evening into Tuesday morning, split it in two:

```
23:00-23:59:59 1 * *;00:00-02:00 2 * * # Monday 11 PM to Tuesday 2 AM
```

## Installation

```bash
Expand Down
6 changes: 6 additions & 0 deletions cronrange.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
// * 0,6 * * # All day on weekends
// 09:00-17:00 1-5 * 4-9 # Weekdays 9 AM to 5 PM, April through September
// 12:00-13:00 * 1,15 * # Noon-1 PM on 1st and 15th of every month
//
// A time range with the end earlier than the start spans midnight, for example 23:00-02:00. Each
// rule is evaluated against a single calendar day, so the dow, dom and month fields are matched
// against the day shown on the clock. With a narrower field that splits the window: 23:00-02:00 1 * *
// matches Monday 00:00-02:00 and Monday 23:00 to midnight, not Monday evening through Tuesday
// morning. Two rules express the latter: 23:00-23:59:59 1 * *;00:00-02:00 2 * *
package cronrange

import (
Expand Down
24 changes: 24 additions & 0 deletions cronrange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,30 @@ func TestMatch(t *testing.T) {
time: time.Date(2024, 1, 1, 16, 30, 0, 0, time.UTC), // Monday 4:30 PM
want: false,
},
{
name: "monday night into tuesday morning, split into two rules",
expr: "23:00-23:59:59 1 * *;00:00-02:00 2 * *",
time: time.Date(2024, 1, 1, 23, 30, 0, 0, time.UTC), // Monday 11:30 PM
want: true,
},
{
name: "monday night into tuesday morning, tail on tuesday",
expr: "23:00-23:59:59 1 * *;00:00-02:00 2 * *",
time: time.Date(2024, 1, 2, 0, 30, 0, 0, time.UTC), // Tuesday 12:30 AM
want: true,
},
{
name: "monday night into tuesday morning, after the tail",
expr: "23:00-23:59:59 1 * *;00:00-02:00 2 * *",
time: time.Date(2024, 1, 2, 2, 0, 1, 0, time.UTC), // Tuesday 2:00:01 AM
want: false,
},
{
name: "monday night into tuesday morning, monday early hours excluded",
expr: "23:00-23:59:59 1 * *;00:00-02:00 2 * *",
time: time.Date(2024, 1, 1, 0, 30, 0, 0, time.UTC), // Monday 12:30 AM
want: false,
},
{
name: "specific month days match",
expr: "12:00-13:00 * 1,15 *",
Expand Down
12 changes: 12 additions & 0 deletions rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,18 @@ func TestMatches(t *testing.T) {
},
wantMatch: []bool{false, true, true, true, true, true, false},
},
{
name: "overnight range with weekday filter, evaluated per calendar day",
rule: "23:00-02:00 1 * *", // Monday
times: []time.Time{
time.Date(2024, 1, 1, 0, 30, 0, 0, time.UTC), // Mon, before the end time
time.Date(2024, 1, 1, 22, 30, 0, 0, time.UTC), // Mon, between end and start
time.Date(2024, 1, 1, 23, 30, 0, 0, time.UTC), // Mon, after the start time
time.Date(2024, 1, 2, 0, 30, 0, 0, time.UTC), // Tue, dow does not match
time.Date(2024, 1, 2, 23, 30, 0, 0, time.UTC), // Tue, dow does not match
},
wantMatch: []bool{true, false, true, false, false},
},
{
name: "specific days",
rule: "10:00-12:00 1,3,5 * *", // Mon,Wed,Fri
Expand Down