cron_calc 0.3.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -1
- data/README.md +33 -17
- data/lib/cron_calc/version.rb +1 -1
- data/lib/cron_calc.rb +56 -27
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aebec718fd55bb74df49580abe4309a41ad0246b2c266a143f9dfac807cd436e
|
4
|
+
data.tar.gz: 1b47dea7541f369800f1f816fdf2160e0721de4a4f8bcdd9434c0b77fdf85876
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6f3349709b4a5babb3d2267f7e8cf1a7e2e51d9a118044e67743cc02b31d34bf5d637b068e825afe9f10c24e34c97a906730363a2c1c309eb003408b2c48586
|
7
|
+
data.tar.gz: fd80e141fd67e56adb122b6acf2dbbeff5572e69868212c749d1f6d67c422d70790a9910cec991a2ef328841f8fea17e2214c6276761124f5e4630f04c613557
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,16 @@
|
|
1
|
+
## [1.0.0] - 2023-12-28
|
2
|
+
|
3
|
+
- Add support for predefined definitions
|
4
|
+
- Add support for joining ,-
|
5
|
+
|
6
|
+
## [0.4.0] - 2023-12-22
|
7
|
+
|
8
|
+
- Added support for named months and wdays
|
9
|
+
- Keyword arguments: before:, after:
|
10
|
+
|
1
11
|
## [0.3.0] - 2023-12-22
|
2
12
|
|
3
|
-
- Added support for DOWs
|
13
|
+
- Added support for DOWs (wdays)
|
4
14
|
|
5
15
|
## [0.2.0] - 2023-12-19
|
6
16
|
|
data/README.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
# CronCalc
|
2
2
|
|
3
|
-
CronCalc
|
3
|
+
**CronCalc**: A Ruby gem for calculating CRON job occurrences. With this gem, you can easily determine when a cron job will occur by providing a cron expression. Key features include the ability to **calculate occurrences**:
|
4
|
+
- **Within a specified period**: Find out all the times your cron job will run during a particular timeframe.
|
5
|
+
- **After a given date**: Determine the next set of occurrences after a specific starting point.
|
6
|
+
- **Before a given date**: Discover when your cron job ran or would have run before a certain date.
|
7
|
+
|
8
|
+
This tool can be used for scheduling, forecasting, and analyzing tasks in systems that use cron for job scheduling.
|
4
9
|
|
5
10
|
## Installation
|
6
11
|
|
@@ -22,8 +27,9 @@ Now, you can use one of three methods `#in`, `#next`, `#last` to determine cron
|
|
22
27
|
### Using `#in`
|
23
28
|
|
24
29
|
Calculates cron job occurrences within a given time period.\
|
25
|
-
|
26
|
-
|
30
|
+
**Parameters:**
|
31
|
+
- `period` - a Range object defining the start and end times for the calculation.\
|
32
|
+
|
27
33
|
|
28
34
|
```ruby
|
29
35
|
period = Time.new(2024, 1, 1, 0, 0)..Time.new(2024, 1, 4, 0, 0)
|
@@ -35,10 +41,10 @@ Calculates cron job occurrences within a given time period.\
|
|
35
41
|
### Using `#next`
|
36
42
|
|
37
43
|
Calculates the next 'n' occurrences of the cron job from a given start time.\
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
44
|
+
**Parameters:**
|
45
|
+
- `count` - (optional, Integer) The number of occurrences to calculate. Defaults to 1.
|
46
|
+
- `after:` - (optional, Time, keyword argument) The start time from which to calculate occurrences. If not provided, defaults to the current time (Time.now).
|
47
|
+
- `max_years` - (optional, Integer, keyword argument) The maximum number of years to search for future occurrences. Defaults to 5.
|
42
48
|
|
43
49
|
```ruby
|
44
50
|
cron_calc.next
|
@@ -47,31 +53,41 @@ Calculates the next 'n' occurrences of the cron job from a given start time.\
|
|
47
53
|
cron_calc.next(3)
|
48
54
|
# => [2023-12-20 05:05:00 +0100, 2023-12-21 05:05:00 +0100, 2023-12-22 05:05:00 +0100]
|
49
55
|
|
50
|
-
cron_calc.next(2, Time.new(2024, 1, 1, 0, 0))
|
56
|
+
cron_calc.next(2, after: Time.new(2024, 1, 1, 0, 0))
|
51
57
|
# => [2024-01-01 05:05:00 +0100, 2024-01-02 05:05:00 +0100]
|
52
58
|
```
|
53
59
|
|
54
60
|
### Using `#last`
|
55
61
|
|
56
62
|
Calculates the last 'n' occurrences of the cron job until a given end time.\
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
63
|
+
**Parameters:**
|
64
|
+
- `count` - (optional, Integer) The number of occurrences to calculate. Defaults to 1.
|
65
|
+
- `before:` - (optional, Time, keyword argument) The end time from which to calculate past occurrences. If not provided, defaults to the current time (Time.now).
|
66
|
+
- `max_years` - (optional, Integer, keyword argument) The maximum number of years to search backward for past occurrences. Defaults to 5.
|
61
67
|
|
62
68
|
```ruby
|
63
69
|
cron_calc.last
|
64
70
|
# => [2023-12-19 05:05:00 +0100]
|
65
71
|
|
66
|
-
cron_calc.last(4, Time.new(2024, 1, 1, 0, 0))
|
72
|
+
cron_calc.last(4, before: Time.new(2024, 1, 1, 0, 0))
|
67
73
|
# => [2023-12-31 05:05:00 +0100, 2023-12-30 05:05:00 +0100, 2023-12-29 05:05:00 +0100, 2023-12-28 05:05:00 +0100]
|
68
74
|
```
|
69
75
|
|
70
|
-
|
76
|
+
### Other examples
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
# You can omit the count parameter
|
80
|
+
CronCalc.new('5 5 */5 * SUN').last(before: Time.new(2020, 1, 1, 0, 0))
|
81
|
+
# => [2019-12-01 05:05:00 +0100]
|
82
|
+
|
83
|
+
# You can combine ',' and '-'
|
84
|
+
CronCalc.new('5 5 5-7,10 FEB *').next(5)
|
85
|
+
# => [2024-02-05 05:05:00 +0100, 2024-02-06 05:05:00 +0100, 2024-02-07 05:05:00 +0100, 2024-02-10 05:05:00 +0100, 2025-02-05 05:05:00 +0100]
|
71
86
|
|
72
|
-
|
73
|
-
|
74
|
-
|
87
|
+
# You can use predefined definitions like @daily, @monthly, etc.
|
88
|
+
CronCalc.new('@monthly').next(3, after: Time.new(2024, 1, 1, 0, 0))
|
89
|
+
# => [2024-01-01 00:00:00 +0100, 2024-02-01 00:00:00 +0100, 2024-03-01 00:00:00 +0100]
|
90
|
+
```
|
75
91
|
|
76
92
|
## Contributing
|
77
93
|
|
data/lib/cron_calc/version.rb
CHANGED
data/lib/cron_calc.rb
CHANGED
@@ -7,6 +7,33 @@ require 'time'
|
|
7
7
|
module CronCalc
|
8
8
|
class Error < StandardError; end
|
9
9
|
|
10
|
+
RANGE = {
|
11
|
+
minutes: 0..59,
|
12
|
+
hours: 0..23,
|
13
|
+
days: 1..31,
|
14
|
+
months: 1..12,
|
15
|
+
wdays: 0..6
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
WDAYS = {
|
19
|
+
'SUN' => '0', 'MON' => '1', 'TUE' => '2', 'WED' => '3',
|
20
|
+
'THU' => '4', 'FRI' => '5', 'SAT' => '6'
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
MONTHS = {
|
24
|
+
'JAN' => '1', 'FEB' => '2', 'MAR' => '3', 'APR' => '4',
|
25
|
+
'MAY' => '5', 'JUN' => '6', 'JUL' => '7', 'AUG' => '8',
|
26
|
+
'SEP' => '9', 'OCT' => '10', 'NOV' => '11', 'DEC' => '12'
|
27
|
+
}.freeze
|
28
|
+
|
29
|
+
PREDEFINED_DEFINITIONS = {
|
30
|
+
'@yearly' => '0 0 1 1 *', '@annually' => '0 0 1 1 *',
|
31
|
+
'@monthly' => '0 0 1 * *',
|
32
|
+
'@weekly' => '0 0 * * 0',
|
33
|
+
'@daily' => '0 0 * * *', '@midnight' => '0 0 * * *',
|
34
|
+
'@hourly' => '0 * * * *'
|
35
|
+
}.freeze
|
36
|
+
|
10
37
|
def self.new(cron_string)
|
11
38
|
Parser.new(cron_string)
|
12
39
|
end
|
@@ -17,19 +44,12 @@ module CronCalc
|
|
17
44
|
class Parser
|
18
45
|
attr_reader :cron_string, :cron_parts
|
19
46
|
|
20
|
-
RANGE = {
|
21
|
-
minutes: 0..59,
|
22
|
-
hours: 0..23,
|
23
|
-
days: 1..31,
|
24
|
-
months: 1..12,
|
25
|
-
dows: 0..7
|
26
|
-
}.freeze
|
27
|
-
|
28
47
|
def initialize(cron_string)
|
29
48
|
@cron_string = cron_string
|
30
49
|
|
31
50
|
raise 'Cron expression is not supported or invalid' unless cron_string_valid?
|
32
51
|
|
52
|
+
@cron_string = normalize_with(cron_string, PREDEFINED_DEFINITIONS) if @cron_string.start_with? '@'
|
33
53
|
@cron_parts = split_cron_string
|
34
54
|
end
|
35
55
|
|
@@ -42,24 +62,24 @@ module CronCalc
|
|
42
62
|
|
43
63
|
# Calculates the next 'n' occurrences of the cron job from a given start time.
|
44
64
|
# @param count [Integer] The number of occurrences to calculate.
|
45
|
-
# @param
|
65
|
+
# @param after [Time] The start time from which to calculate occurrences.
|
46
66
|
# @param max_years [Integer] The maximum number of years to consider for the period.
|
47
67
|
# @return [Array<Time>] An array of the next 'n' occurrences.
|
48
|
-
def next(count = 1,
|
68
|
+
def next(count = 1, after: Time.now, max_years: 5)
|
49
69
|
occurrences(
|
50
|
-
|
70
|
+
after..(after + (60 * 60 * 24 * 365 * max_years)),
|
51
71
|
count
|
52
72
|
)
|
53
73
|
end
|
54
74
|
|
55
75
|
# Calculates the last 'n' occurrences of the cron job until a given end time.
|
56
76
|
# @param count [Integer] The number of past occurrences to calculate.
|
57
|
-
# @param
|
77
|
+
# @param before [Time] The end time until which to calculate occurrences.
|
58
78
|
# @param max_years [Integer] The maximum number of years to consider for the period.
|
59
79
|
# @return [Array<Time>] An array of the last 'n' occurrences.
|
60
|
-
def last(count = 1,
|
80
|
+
def last(count = 1, before: Time.now, max_years: 5)
|
61
81
|
occurrences(
|
62
|
-
(
|
82
|
+
(before - (60 * 60 * 24 * 365 * max_years))..before,
|
63
83
|
count,
|
64
84
|
reverse: true
|
65
85
|
)
|
@@ -69,7 +89,7 @@ module CronCalc
|
|
69
89
|
|
70
90
|
def occurrences(period, count = nil, reverse: false)
|
71
91
|
time_combinations = generate_time_combinations(period, reverse).lazy
|
72
|
-
wdays = parse_cron_part(:
|
92
|
+
wdays = parse_cron_part(:wdays)
|
73
93
|
|
74
94
|
time_combinations.each_with_object([]) do |(year, month, day, hour, minute), occ|
|
75
95
|
break occ if count && occ.length == count
|
@@ -94,8 +114,8 @@ module CronCalc
|
|
94
114
|
minutes: splitted[0],
|
95
115
|
hours: splitted[1],
|
96
116
|
days: splitted[2],
|
97
|
-
months: splitted[3],
|
98
|
-
|
117
|
+
months: normalize_with(splitted[3], MONTHS),
|
118
|
+
wdays: normalize_with(splitted[4], WDAYS)
|
99
119
|
}
|
100
120
|
end
|
101
121
|
|
@@ -103,31 +123,40 @@ module CronCalc
|
|
103
123
|
%i[minutes hours days months].map { |unit| parse_cron_part(unit) }
|
104
124
|
end
|
105
125
|
|
106
|
-
# rubocop:disable Metrics
|
107
126
|
def parse_cron_part(time_unit)
|
108
127
|
range = RANGE[time_unit]
|
109
128
|
part = cron_parts[time_unit]
|
110
129
|
|
111
|
-
|
130
|
+
if part.include?(',')
|
131
|
+
part.split(',').flat_map { |e| parse_single_element(e, range) }.uniq.sort
|
132
|
+
else
|
133
|
+
parse_single_element(part, range)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def parse_single_element(element, range)
|
138
|
+
case element
|
112
139
|
when '*'
|
113
140
|
range.to_a
|
114
|
-
when /,/
|
115
|
-
part.split(',').map(&:to_i)
|
116
141
|
when /-/
|
117
|
-
(
|
142
|
+
(element.split('-').first.to_i..element.split('-').last.to_i).to_a
|
118
143
|
when %r{/}
|
119
|
-
range.step(
|
144
|
+
range.step(element.split('/').last.to_i).to_a
|
120
145
|
else
|
121
|
-
[
|
146
|
+
[element.to_i]
|
122
147
|
end
|
123
148
|
end
|
124
|
-
|
149
|
+
|
150
|
+
def normalize_with(string, mapping)
|
151
|
+
mapping.inject(string) { |str, (k, v)| str.gsub(k, v) }
|
152
|
+
end
|
125
153
|
|
126
154
|
def cron_string_valid?
|
155
|
+
predefined = /\A@(yearly|annually|monthly|weekly|daily|midnight|hourly)\z/
|
127
156
|
# rubocop:disable Layout/LineLength
|
128
|
-
|
157
|
+
standard = %r{\A(\*|(\*/[0-5]?\d)|([0-5]?\d)(-(?:[0-5]?\d))?(,([0-5]?\d)(-(?:[0-5]?\d))?)*) (\*|(\*/[01]?\d|2[0-3])|([01]?\d|2[0-3])(-(?:[01]?\d|2[0-3]))?(,([01]?\d|2[0-3])(-(?:[01]?\d|2[0-3]))?)*|(\*/\d+)) (\*|(\*/[12]?\d|3[01])|([12]?\d|3[01])(-(?:[12]?\d|3[01]))?(,([12]?\d|3[01])(-(?:[12]?\d|3[01]))?)*|(\*/\d+)) (\*|(\*/[1-9]|1[0-2])|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC|[1-9]|1[0-2])(-(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC|[1-9]|1[0-2]))?(,(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC|[1-9]|1[0-2])(-(?:JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC|[1-9]|1[0-2]))?)*|(\*/\d+)) (\*|(\*/[0-6])|(SUN|MON|TUE|WED|THU|FRI|SAT|[0-6])(-(?:SUN|MON|TUE|WED|THU|FRI|SAT|[0-6]))?(,(SUN|MON|TUE|WED|THU|FRI|SAT|[0-6])(-(?:SUN|MON|TUE|WED|THU|FRI|SAT|[0-6]))?)*|(\*/[0-6]+))\z}
|
129
158
|
# rubocop:enable Layout/LineLength
|
130
|
-
cron_string.match?(
|
159
|
+
cron_string.match?(predefined) || cron_string.match?(standard)
|
131
160
|
end
|
132
161
|
end
|
133
162
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cron_calc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jakub Miziński
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-12-
|
11
|
+
date: 2023-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |-
|
14
14
|
Calculates cron job occurrences within a specified period
|