Class: AWSCronParser::Parser

Inherits:
Object
  • Object
show all
Includes:
Helpers
Defined in:
lib/aws_cron_parser/parser.rb

Instance Method Summary collapse

Methods included from Helpers

included

Constructor Details

#initialize(source, time_source = Time) ⇒ Parser

Returns a new instance of Parser.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/aws_cron_parser/parser.rb', line 9

def initialize(source, time_source = Time)
  @original_source = source
  @time_source = time_source

  validate!

  # Route to appropriate parser
  @parser = if RATE_REGEX.match?(@original_source)
              AWSCronParser::Parsers::AWSRate.new(@original_source, @time_source)
            elsif AT_REGEX.match?(@original_source)
              AWSCronParser::Parsers::AWSAt.new(@original_source, @time_source)
            elsif AWS_CRON_REGEX.match?(@original_source) || @original_source.start_with?('@')
              AWSCronParser::Parsers::AWSCron.new(@original_source, @time_source)
            else
              AWSCronParser::Parsers::QuartzCron.new(@original_source, @time_source)
            end
end

Instance Method Details

#describeObject



128
129
130
# File 'lib/aws_cron_parser/parser.rb', line 128

def describe
  Describer.describe(@original_source)
end

#errorsObject



148
149
150
# File 'lib/aws_cron_parser/parser.rb', line 148

def errors
  @errors || []
end

#expressionObject



124
125
126
# File 'lib/aws_cron_parser/parser.rb', line 124

def expression
  @original_source
end

#last(now = @time_source.now) ⇒ Object



36
37
38
39
40
41
42
43
44
# File 'lib/aws_cron_parser/parser.rb', line 36

def last(now = @time_source.now)
  if @parser.is_a?(AWSCronParser::Parsers::AWSCron) ||
     @parser.is_a?(AWSCronParser::Parsers::AWSRate) ||
     @parser.is_a?(AWSCronParser::Parsers::AWSAt)
    raise ArgumentError, 'last() not supported for special patterns'
  end

  @parser.last(now)
end

#next(now = @time_source.now) ⇒ Object



27
28
29
30
31
32
33
34
# File 'lib/aws_cron_parser/parser.rb', line 27

def next(now = @time_source.now)
  @parser.next(now)
rescue ZeroDivisionError => e
  # Normalize low-level arithmetic errors from underlying parser into
  # a user-facing ArgumentError so callers (and controllers) can
  # return a proper 4xx validation response instead of crashing.
  raise ArgumentError, "Invalid CRON expression: #{e.message}"
end

#next_runs(count = 5, from = @time_source.now) ⇒ Array<Time>

Get multiple next runs (shows unique occurrences for UI when appropriate)

Parameters:

  • count (Integer) (defaults to: 5)

    Number of next runs to calculate

  • from (Time) (defaults to: @time_source.now)

    Starting time (defaults to now)

Returns:

  • (Array<Time>)

    Array of next execution times



50
51
52
53
# File 'lib/aws_cron_parser/parser.rb', line 50

def next_runs(count = 5, from = @time_source.now)
  # Always show all executions - the UI can handle pagination/filtering if needed
  next_runs_all(count, from)
end

#next_runs_all(count = 5, from = @time_source.now) ⇒ Array<Time>

Get ALL next runs (raw behavior - every single execution)

Parameters:

  • count (Integer) (defaults to: 5)

    Number of next runs to calculate

  • from (Time) (defaults to: @time_source.now)

    Starting time (defaults to now)

Returns:

  • (Array<Time>)

    Array of next execution times

Raises:

  • (ArgumentError)


59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/aws_cron_parser/parser.rb', line 59

def next_runs_all(count = 5, from = @time_source.now)
  raise ArgumentError, 'count must be positive' if count <= 0

  results = []
  current = from

  count.times do
    current = @parser.next(current)
    # A one-time at() schedule stops yielding once its instant has passed.
    break if current.nil?

    results << current
  end

  results
end

#next_unique_dates(count, from = @time_source.now) ⇒ Object

Get unique dates (remove time component)



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/aws_cron_parser/parser.rb', line 77

def next_unique_dates(count, from = @time_source.now)
  seen_dates = Set.new
  results = []
  current = from

  while results.length < count && results.length < 1000 # Safety limit
    current = self.next(current)
    break if current.nil?

    date_key = current.to_date

    next if seen_dates.include?(date_key)

    seen_dates.add(date_key)
    # Set to start of day for cleaner display
    results << current.beginning_of_day
  end

  results
end

#next_unique_hours(count, from = @time_source.now) ⇒ Object

Get unique hours (remove minute component)



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/aws_cron_parser/parser.rb', line 99

def next_unique_hours(count, from = @time_source.now)
  seen_hours = Set.new
  results = []
  current = from

  while results.length < count && results.length < 1000 # Safety limit
    current = self.next(current)
    break if current.nil?

    hour_key = [current.to_date, current.hour]

    next if seen_hours.include?(hour_key)

    seen_hours.add(hour_key)
    # Set to start of hour for cleaner display
    results << current.beginning_of_hour
  end

  results
end

#sourceObject



120
121
122
# File 'lib/aws_cron_parser/parser.rb', line 120

def source
  @parser.source
end

#valid?Boolean

Returns:

  • (Boolean)


143
144
145
146
# File 'lib/aws_cron_parser/parser.rb', line 143

def valid?
  validate
  errors.empty?
end

#validateObject



136
137
138
139
140
141
# File 'lib/aws_cron_parser/parser.rb', line 136

def validate
  @errors = nil
  Validator.validate(@original_source)
rescue ArgumentError => e
  @errors = [e.message]
end

#validate!Object



132
133
134
# File 'lib/aws_cron_parser/parser.rb', line 132

def validate!
  Validator.validate(@original_source)
end