Class: Philiprehberger::CronParser::Expression
- Inherits:
-
Object
- Object
- Philiprehberger::CronParser::Expression
- Defined in:
- lib/philiprehberger/cron_parser/expression.rb
Overview
Represents a parsed 5-field cron expression
Constant Summary collapse
- FIELD_RANGES =
{ minute: { min: 0, max: 59 }, hour: { min: 0, max: 23 }, day: { min: 1, max: 31 }, month: { min: 1, max: 12 }, weekday: { min: 0, max: 6 } }.freeze
- FIELD_NAMES_MAP =
{ minute: nil, hour: nil, day: nil, month: Field::MONTH_NAMES, weekday: Field::WEEKDAY_NAMES }.freeze
- HUMAN_LABELS =
{ minute: 'minute', hour: 'hour', day: 'day of month', month: 'month', weekday: 'day of week' }.freeze
- ALIASES =
{ '@yearly' => '0 0 1 1 *', '@annually' => '0 0 1 1 *', '@monthly' => '0 0 1 * *', '@weekly' => '0 0 * * 0', '@daily' => '0 0 * * *', '@midnight' => '0 0 * * *', '@hourly' => '0 * * * *' }.freeze
Instance Attribute Summary collapse
-
#expression ⇒ String
readonly
The original (post-alias expansion) expression.
Instance Method Summary collapse
-
#count_in(from:, to:) ⇒ Integer
Count occurrences within a time window [from, to].
-
#human_readable ⇒ String
(also: #description)
Return a human-readable description of the expression.
-
#initialize(expr) ⇒ Expression
constructor
A new instance of Expression.
-
#matches?(time) ⇒ Boolean
Check if a given time matches this cron expression.
-
#next(from: Time.now) ⇒ Time
Calculate the next occurrence after the given time.
-
#next_n(count, from: Time.now) ⇒ Array<Time>
Calculate the next N occurrences after the given time.
-
#prev(from: Time.now) ⇒ Time
Calculate the previous occurrence before the given time.
Constructor Details
#initialize(expr) ⇒ Expression
Returns a new instance of Expression.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/philiprehberger/cron_parser/expression.rb', line 48 def initialize(expr) stripped = expr.strip stripped = ALIASES[stripped.downcase] if stripped.start_with?('@') raise Error, "Unknown cron alias: #{expr.strip}" if stripped.nil? @expression = stripped parts = @expression.split(/\s+/) raise Error, "Expected 5 fields, got #{parts.size}: #{@expression}" unless parts.size == 5 @fields = {} FIELD_RANGES.each_with_index do |(name, range), index| @fields[name] = Field.new(parts[index], min: range[:min], max: range[:max], names: FIELD_NAMES_MAP[name]) end end |
Instance Attribute Details
#expression ⇒ String (readonly)
Returns the original (post-alias expansion) expression.
44 45 46 |
# File 'lib/philiprehberger/cron_parser/expression.rb', line 44 def expression @expression end |
Instance Method Details
#count_in(from:, to:) ⇒ Integer
Count occurrences within a time window [from, to].
The window is inclusive on both ends; ‘from` is treated as the cursor’s starting point so an exact match at ‘from` counts only if it lies on a minute boundary that the schedule fires on.
119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/philiprehberger/cron_parser/expression.rb', line 119 def count_in(from:, to:) raise Error, '`to` must be greater than or equal to `from`' if to < from count = 0 cursor = round_to_minute(from) - 60 loop do cursor = self.next(from: cursor) break if cursor > to count += 1 end count end |
#human_readable ⇒ String Also known as: description
Return a human-readable description of the expression
136 137 138 139 140 141 142 143 144 |
# File 'lib/philiprehberger/cron_parser/expression.rb', line 136 def human_readable parts = [] parts << minute_description parts << hour_description parts << day_description parts << month_description parts << weekday_description parts.compact.join(', ') end |
#matches?(time) ⇒ Boolean
Check if a given time matches this cron expression
67 68 69 70 71 72 73 |
# File 'lib/philiprehberger/cron_parser/expression.rb', line 67 def matches?(time) @fields[:minute].matches?(time.min) && @fields[:hour].matches?(time.hour) && @fields[:day].matches?(time.day) && @fields[:month].matches?(time.month) && @fields[:weekday].matches?(time.wday) end |
#next(from: Time.now) ⇒ Time
Calculate the next occurrence after the given time
80 81 82 |
# File 'lib/philiprehberger/cron_parser/expression.rb', line 80 def next(from: Time.now) find_occurrence(from, direction: :forward) end |
#next_n(count, from: Time.now) ⇒ Array<Time>
Calculate the next N occurrences after the given time
98 99 100 101 102 103 104 105 106 107 |
# File 'lib/philiprehberger/cron_parser/expression.rb', line 98 def next_n(count, from: Time.now) results = [] current = from count.times do current = self.next(from: current) results << current current += 60 end results end |
#prev(from: Time.now) ⇒ Time
Calculate the previous occurrence before the given time
89 90 91 |
# File 'lib/philiprehberger/cron_parser/expression.rb', line 89 def prev(from: Time.now) find_occurrence(from, direction: :backward) end |