cron_calc 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5757a8135782488cf246c22cd72ccc0aa04e00d06a726203df41205c0df79ef8
4
- data.tar.gz: d33394dd5136e58f41a4ea7d8e6759d5e51326e61bb9bc4303d9778d6f85de60
3
+ metadata.gz: df5dd3a2f576d78996d783668af59a058a4fd9256072dfa25b84760d64e09797
4
+ data.tar.gz: 922e53ae27d369035d3b7fff81e1ba624756fa365c30694e6871abc54421473e
5
5
  SHA512:
6
- metadata.gz: 708988f704dee9a33f9331c3508485c2bcc45d7184fac956c590dad69e468e8eabb282a863d391f13f655c1816ef2aae62e77b8d66db755cec4122530ddde178
7
- data.tar.gz: 4dfc4c4c89ea7e983d95837dfb014992c2916b0cb54d731cb2f95441687cddf94bfeb90133cc180fddd4e3a96d23254819c8ec416db1498200270a67c291af5b
6
+ metadata.gz: 85a0d0ea11962ee78495e6c6c8ee40ea9695d20df2635efbb67cdc32502086032b3aa85aaa419b39cc1a736a31c6d1ecc577afd60b571d4e8d120c5adcd922fc
7
+ data.tar.gz: aab193b3c8afe9551dd46fe1b9e0061702cc69e3fa739c08c774d5f77ef40dabbd5c90c816b93a1e864d2e05c6c5278eda102c07649c83afd3a43553c5cc5ef8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
- ## [Unreleased]
1
+ ## [0.2.0] - 2023-12-19
2
2
 
3
- ## [0.1.0] - 2023-11-27
3
+ - Added #next method
4
+ - Added #last method
5
+
6
+ ## [0.1.0] - 2023-12-18
4
7
 
5
8
  - Initial release
data/README.md CHANGED
@@ -4,25 +4,75 @@ CronCalc: A Ruby gem for calculating and analyzing scheduled CRON job occurrence
4
4
 
5
5
  ## Installation
6
6
 
7
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
7
+ Install the gem by executing:
8
8
 
9
- Install the gem and add to the application's Gemfile by executing:
9
+ $ gem install cron_calc
10
10
 
11
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
11
+ ## Usage
12
12
 
13
- If bundler is not being used to manage dependencies, install the gem by executing:
13
+ After installing `cron_calc` you can initialize `CronCalc` with the CRON string.
14
14
 
15
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
15
+ ```ruby
16
+ require 'cron_calc'
17
+ cron_calc = CronCalc.new('5 5 * * *')
18
+ ```
16
19
 
17
- ## Usage
20
+ Now, you can use one of three methods `#in`, `#next`, `#last` to determine cron job occurrencies within specified period.
21
+
22
+ ### Using `#in`
23
+
24
+ Calculates cron job occurrences within a given time period.
25
+ @param period [Range] The time period for which to calculate cron job occurrences.
26
+ @return [Array<Time>] An array of Time instances representing each occurrence.
27
+
28
+ ```ruby
29
+ period = Time.new(2024, 1, 1, 0, 0)..Time.new(2024, 1, 4, 0, 0)
30
+ cron_calc.in(period)
31
+
32
+ # => [2024-01-01 05:05:00 +0100, 2024-01-02 05:05:00 +0100, 2024-01-03 05:05:00 +0100]
33
+ ```
34
+
35
+ ### Using `#next`
36
+
37
+ Calculates the next 'n' occurrences of the cron job from a given start time.
38
+ @param count [Integer] The number of occurrences to calculate. Defaults to `1`.
39
+ @param period_start [Time] The start time from which to calculate occurrences. Defaults to `Time.now`.
40
+ @param max_years [Integer] The maximum number of years to consider for the period. Defaults to `5`.
41
+ @return [Array<Time>] An array of the next 'n' occurrences.
42
+
43
+ ```ruby
44
+ cron_calc.next
45
+ # => [2023-12-20 05:05:00 +0100]
46
+
47
+ cron_calc.next(3)
48
+ # => [2023-12-20 05:05:00 +0100, 2023-12-21 05:05:00 +0100, 2023-12-22 05:05:00 +0100]
49
+
50
+ cron_calc.next(2, Time.new(2024, 1, 1, 0, 0))
51
+ # => [2024-01-01 05:05:00 +0100, 2024-01-02 05:05:00 +0100]
52
+ ```
53
+
54
+ ### Using `#last`
55
+
56
+ Calculates the last 'n' occurrences of the cron job until a given end time.
57
+ @param count [Integer] The number of past occurrences to calculate.
58
+ @param period_end [Time] The end time until which to calculate occurrences.
59
+ @param max_years [Integer] The maximum number of years to consider for the period.
60
+ @return [Array<Time>] An array of the last 'n' occurrences.
18
61
 
19
- TODO: Write usage instructions here
62
+ ```ruby
63
+ cron_calc.last
64
+ # => [2023-12-19 05:05:00 +0100]
20
65
 
21
- ## Development
66
+ cron_calc.last(4, Time.new(2024, 1, 1, 0, 0))
67
+ # => [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
+ ```
22
69
 
23
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
70
+ ## Unsupported features
24
71
 
25
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
72
+ - DOW (Day of Week) - always require *
73
+ - Named DOW and months (SUN-SAT, JAN-DEC)
74
+ - Joining characters , - /
75
+ - Predefined definitions (@yearly, @monthly, @weekly, @daily, @midnight, @hourly)
26
76
 
27
77
  ## Contributing
28
78
 
data/cron_calc.gemspec CHANGED
@@ -8,8 +8,9 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['Jakub Miziński']
9
9
  spec.email = ['jakubmizinski@gmail.com']
10
10
 
11
- spec.summary = 'calculates cron job occurrences'
12
- spec.description = 'calculates cron job occurrences within a specified period'
11
+ spec.summary = 'Calculates cron job occurrences'
12
+ spec.description = 'Calculates cron job occurrences within a specified period \n
13
+ or determines next/last "n" occurrences based on a specified time.'
13
14
  spec.homepage = 'https://github.com/mizinsky/cron_calc'
14
15
  spec.license = 'MIT'
15
16
  spec.required_ruby_version = '>= 2.6.0'
@@ -30,10 +31,4 @@ Gem::Specification.new do |spec|
30
31
  spec.bindir = 'exe'
31
32
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
32
33
  spec.require_paths = ['lib']
33
-
34
- # Uncomment to register a new dependency of your gem
35
- spec.add_dependency 'rspec', '~> 3.12'
36
-
37
- # For more information and examples about making a new gem, check out our
38
- # guide at: https://bundler.io/guides/creating_gem.html
39
34
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CronCalc
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/cron_calc.rb CHANGED
@@ -7,15 +7,15 @@ require 'time'
7
7
  module CronCalc
8
8
  class Error < StandardError; end
9
9
 
10
- def self.new(cron_string, period)
11
- Parser.new(cron_string, period)
10
+ def self.new(cron_string)
11
+ Parser.new(cron_string)
12
12
  end
13
13
 
14
14
  # The Parser class provides functionality to parse and calculate occurrences
15
15
  # of cron jobs within a given time period. It interprets cron strings and
16
16
  # calculates when cron jobs will occur
17
17
  class Parser
18
- attr_reader :cron_string, :cron_parts, :period
18
+ attr_reader :cron_string, :cron_parts
19
19
 
20
20
  RANGE = {
21
21
  minutes: 0..59,
@@ -24,24 +24,66 @@ module CronCalc
24
24
  months: 1..12
25
25
  }.freeze
26
26
 
27
- def initialize(cron_string, period)
27
+ def initialize(cron_string)
28
28
  @cron_string = cron_string
29
- @period = period
29
+
30
+ raise 'Cron expression is not supported or invalid' unless cron_string_valid?
31
+
30
32
  @cron_parts = split_cron_string
31
33
  end
32
34
 
33
- def occurrences
34
- raise 'Cron expression is not supported or invalid' unless cron_string_valid?
35
+ # Calculates cron job occurrences within a given time period.
36
+ # @param period [Range] The time period for which to calculate cron job occurrences.
37
+ # @return [Array<Time>] An array of Time instances representing each occurrence.
38
+ def in(period)
39
+ occurrences(period)
40
+ end
41
+
42
+ # Calculates the next 'n' occurrences of the cron job from a given start time.
43
+ # @param count [Integer] The number of occurrences to calculate.
44
+ # @param period_start [Time] The start time from which to calculate occurrences.
45
+ # @param max_years [Integer] The maximum number of years to consider for the period.
46
+ # @return [Array<Time>] An array of the next 'n' occurrences.
47
+ def next(count = 1, period_start = Time.now, max_years = 5)
48
+ occurrences(
49
+ period_start..(period_start + (60 * 60 * 24 * 365 * max_years)),
50
+ count
51
+ )
52
+ end
35
53
 
36
- minutes, hours, days, months, years = parse_cron_expression
54
+ # Calculates the last 'n' occurrences of the cron job until a given end time.
55
+ # @param count [Integer] The number of past occurrences to calculate.
56
+ # @param period_end [Time] The end time until which to calculate occurrences.
57
+ # @param max_years [Integer] The maximum number of years to consider for the period.
58
+ # @return [Array<Time>] An array of the last 'n' occurrences.
59
+ def last(count = 1, period_end = Time.now, max_years = 5)
60
+ occurrences(
61
+ (period_end - (60 * 60 * 24 * 365 * max_years))..period_end,
62
+ count,
63
+ reverse: true
64
+ )
65
+ end
66
+
67
+ private
68
+
69
+ def occurrences(period, count = nil, reverse: false)
70
+ time_combinations = generate_time_combinations(period, reverse).lazy
71
+
72
+ time_combinations.each_with_object([]) do |(year, month, day, hour, minute), occ|
73
+ break occ if count && occ.length == count
37
74
 
38
- years.product(months, days, hours, minutes).each_with_object([]) do |(year, month, day, hour, minute), occ|
39
75
  time = Time.new(year, month, day, hour, minute)
40
76
  occ << time if Date.valid_date?(year, month, day) && period.include?(time)
41
77
  end
42
78
  end
43
79
 
44
- private
80
+ def generate_time_combinations(period, reverse)
81
+ minutes, hours, days, months = parse_cron_expression
82
+ years = (period.min.year..period.max.year).to_a
83
+
84
+ combinations = years.product(months, days, hours, minutes)
85
+ reverse ? combinations.reverse : combinations
86
+ end
45
87
 
46
88
  def split_cron_string
47
89
  splitted = cron_string.split
@@ -55,7 +97,7 @@ module CronCalc
55
97
  end
56
98
 
57
99
  def parse_cron_expression
58
- %i[minutes hours days months].map { |unit| parse_cron_part(unit) } << (period.min.year..period.max.year).to_a
100
+ %i[minutes hours days months].map { |unit| parse_cron_part(unit) }
59
101
  end
60
102
 
61
103
  # rubocop:disable Metrics
metadata CHANGED
@@ -1,30 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cron_calc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.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-18 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: rspec
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '3.12'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '3.12'
27
- description: calculates cron job occurrences within a specified period
11
+ date: 2023-12-19 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |-
14
+ Calculates cron job occurrences within a specified period \n
15
+ or determines next/last "n" occurrences based on a specified time.
28
16
  email:
29
17
  - jakubmizinski@gmail.com
30
18
  executables: []
@@ -64,8 +52,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
52
  - !ruby/object:Gem::Version
65
53
  version: '0'
66
54
  requirements: []
67
- rubygems_version: 3.4.22
55
+ rubygems_version: 3.5.1
68
56
  signing_key:
69
57
  specification_version: 4
70
- summary: calculates cron job occurrences
58
+ summary: Calculates cron job occurrences
71
59
  test_files: []