recurring_date 0.0.3 → 0.1.1

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
- SHA1:
3
- metadata.gz: d4cc8eff5210dd36470912daacacd4a4a44f7109
4
- data.tar.gz: d339946cc56e30491139b5577a63033e963be901
2
+ SHA256:
3
+ metadata.gz: 7852f2274c200712705a14f593a92ad3b68d69a935b4dd81d4d6ee29b3b83035
4
+ data.tar.gz: 20f777337f3cb1afde4cdc3fc03f95833a70b1816116f486f4887e2724fda14e
5
5
  SHA512:
6
- metadata.gz: 4465192a86991d9f4cd3fb2d0d9eede1845ddc690cc39a2c9990d7dd0947c6935fdc2ea4d417e3856a399e15fa327514168f3813a5303aa92a99e11bb168f029
7
- data.tar.gz: 31e51294b9b93401ae693aee6d2c61b01ebb25947835f5bd41d6e86bff79cf608dd69a9eba680de394e955459c4431152e788a5c8427a0fdb4d253381184f4e2
6
+ metadata.gz: 13b085b3ccd9bff2227f451979adadf7be355ca0da35d09a15827848217d0e59d3bdd150447e597866a63f42ddbd68a59fb55ae8b50b17e22cc589c1eb738eba
7
+ data.tar.gz: 9744b7f105c3aa9099210208bd4ee5447c9b91fc2aea3d3919e390f628cbbf4012f16f5841ee52f5da533b8a1e3c4f7df44c4a2e2fcc07f8b41445da8e5b8070
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /spec/reports/
3
+ /tmp/
4
+
5
+ # rspec failure tracking
6
+ .rspec_status
7
+
8
+ # ignore gem releses
9
+ *.gem
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,31 @@
1
+ image: "reg01.binarapps.com/docker-images/ruby-rvm:2.3.1"
2
+
3
+ variables:
4
+
5
+ cache:
6
+ key: "$CI_BUILD_REF_NAME"
7
+
8
+ stages:
9
+ - build
10
+ - test
11
+
12
+ before_script:
13
+ - rvm current
14
+ - bundle install --jobs $(nproc) --path /cache
15
+
16
+ bundle install:
17
+ stage: build
18
+ before_script: []
19
+ script:
20
+ - rvm current
21
+ - bundle install --jobs $(nproc) --path /cache
22
+
23
+ rspec:
24
+ stage: test
25
+ script:
26
+ - bundle exec rspec -fp
27
+
28
+ rubocop:
29
+ stage: test
30
+ script:
31
+ - bundle exec rubocop
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,39 @@
1
+ AllCops:
2
+ Include:
3
+ - '**/Gemfile'
4
+ Exclude:
5
+ - '**/Gemfile*'
6
+ - '**/*.gemspec'
7
+ TargetRubyVersion: 2.3
8
+ Style/WhileUntilModifier:
9
+ MaxLineLength: 120
10
+ Style/WhileUntilModifier:
11
+ MaxLineLength: 120
12
+ Metrics/LineLength:
13
+ Max: 120
14
+ Metrics/MethodLength:
15
+ Max: 25
16
+ Metrics/AbcSize:
17
+ Max: 50
18
+ Metrics/ClassLength:
19
+ Enabled: false
20
+ Metrics/BlockLength:
21
+ Enabled: false
22
+ Style/Documentation:
23
+ Enabled: false
24
+ Style/AlignParameters:
25
+ EnforcedStyle: with_fixed_indentation
26
+ Style/MultilineMethodCallIndentation:
27
+ EnforcedStyle: indented
28
+ Style/DotPosition:
29
+ EnforcedStyle: trailing
30
+ Style/MultilineHashBraceLayout:
31
+ Enabled: false
32
+ Style/Lambda:
33
+ Enabled: false
34
+ Style/CharacterLiteral:
35
+ Enabled: false
36
+ Style/CharacterLiteral:
37
+ Enabled: false
38
+ Style/FrozenStringLiteralComment:
39
+ Enabled: false
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ recurring_date
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.6.5
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,35 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ recurring_date (0.1.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.3)
10
+ rake (10.5.0)
11
+ rspec (3.5.0)
12
+ rspec-core (~> 3.5.0)
13
+ rspec-expectations (~> 3.5.0)
14
+ rspec-mocks (~> 3.5.0)
15
+ rspec-core (3.5.4)
16
+ rspec-support (~> 3.5.0)
17
+ rspec-expectations (3.5.0)
18
+ diff-lcs (>= 1.2.0, < 2.0)
19
+ rspec-support (~> 3.5.0)
20
+ rspec-mocks (3.5.0)
21
+ diff-lcs (>= 1.2.0, < 2.0)
22
+ rspec-support (~> 3.5.0)
23
+ rspec-support (3.5.0)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ bundler (~> 1.17)
30
+ rake (~> 10.0)
31
+ recurring_date!
32
+ rspec (~> 3.0)
33
+
34
+ BUNDLED WITH
35
+ 1.17.3
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Paweł Placzyński
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # recurring_date
2
+
3
+ Iterate over a set of dates, giving an iteration conditions.
4
+
5
+ This gem provides an enumerator `RecurringDate::Enumerator`, selecting specific dates due to the recursion pattern.
6
+
7
+ `RecurringDate::Enumerator` is lazy so pattern can be applied to an infinite set of dates.
8
+
9
+ The enumerator operates on objects that implements the `Enumerator#each` and yields `Date`.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'recurring_date'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install recurring_date
26
+
27
+ ## Usage
28
+
29
+
30
+ ### `RecurringDate`
31
+
32
+ `RecurringDate` module adds two methods to class `Date`:
33
+
34
+ | Method | Description
35
+ |------------|-------------
36
+ | `#mweek` | Returns a number - n'th occurence of the week day in the month.
37
+ | `#to_enum` | Returns `RecurringDate::Enumerator` enumerator with given range from `self` iterating forever (infinite set).
38
+
39
+ ### `RecurringDate::Enumerator`
40
+
41
+ The enumerator implements bunch of chainable methods to provide simple DSL for selecting wanted recursion pattern.
42
+
43
+ | Pattern | DSL
44
+ |----------------------------------------------------------|-----
45
+ | dates matching `condition` | `enumerator.select { ❘d❘ condition }`
46
+ | dates not matching `condition` | `enumerator.reject { ❘d❘ condition }`
47
+ | dates matching `condition` (with index `i`) | `enumerator.select_with_index { ❘d, i❘ condition }`
48
+ | dates from beginning as long as `condition` is fulfilled | `enumerator.take_while { ❘d❘ condition }`
49
+ | `n` dates from beginning | `enumerator.take(n)`
50
+ | every 4th of October | `enumerator.month(10).mday(4)`
51
+ | every 3rd and 23rd of August | `enumerator.month(8).mday(3, 23)`
52
+ | every 17th June and July | `enumerator.month(6, 7).mday(17)`
53
+ | every 10th and 12th of February and April | `enumerator.month(2, 4).mday(10, 12)`
54
+ | every 13th of the month | `enumerator.mday(13)`
55
+ | every 21st and 23rd of the month | `enumerator.mday(21, 23)`
56
+ | every Friday | `enumerator.wday(5)`
57
+ | every Saturday and Sunday | `enumerator.wday(6, 0)`
58
+ | every Saturday and Sunday | `enumerator.matching(6, 0) { ❘d❘ d.wday }`
59
+ | every Saturday and Sunday | `enumerator.matching(6, 0, &:wday)`
60
+ | every 4th day | `enumerator.pattern(4)`
61
+ | every 7th or 10th day | `enumerator.pattern(7, 10)`
62
+ | every second Friday | `enumerator.wday(5).pattern(2)`
63
+ | every 2nd Monday of the month | `enumerator.wday(1).mweek(2)`
64
+ | 2nd and 4th Sunday of the month | `enumerator.wday(0).mweek(2,4)`
65
+ | 3rd Tuesday and Wednesday of the month | `enumerator.wday(2,3).mweek(3)`
66
+ | until `date` | `enumerator.until(date)`
67
+
68
+ ###### NOTE
69
+
70
+ * There is a method `RecurringDate::Enumerator.eternity` that returns `RecurringDate::Enumerator` instance that iterates perpetualy over every day after _1970-01-01_.
71
+ * The `RecurringDate::Enumerator.from(date)` method does the same, but from `date`.
72
+ * Every enumerator method (except `select`, `select_with_index`, `reject`, `take`, `take_while` and `until`) has a corresponding method with `not_` prefix.
73
+ * For `rails` models the pattern can be used to select records, like: `Model.where('column::date IN (?)', dates)`.
74
+
75
+ ### Example
76
+
77
+ require 'recurring_date'
78
+ rule = RecurringDate::Enumerator.eternity
79
+ rule.wday(5).mweek(1) # => enumerator of all first Fridays of a month
80
+ rule.pattern(2).until(Date.new(2020, 8, 1)) # => enumerator of every second day until 2020-08-01
81
+ rule.wday(6,0).mweek(2,4).take(8) # => enumerator of next four 2nd and 4th weekends of a month
82
+ rule.to_a # => array of `Date` instances (be careful - it can be infinite)
83
+
84
+ ## Development
85
+
86
+ 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.
87
+
88
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `lib/recurring_date/version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
89
+
90
+ ## Contributing
91
+
92
+ Bug reports and pull requests are welcome on GitHub at https://github.com/placek/recurring_date.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'recurring_date'
5
+
6
+ require 'irb'
7
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
@@ -0,0 +1,132 @@
1
+ require 'date'
2
+
3
+ module RecurringDate
4
+ class Enumerator < ::Enumerator
5
+ def initialize(range)
6
+ super() do |result|
7
+ begin
8
+ range.each { |val| block_given? ? yield(result, val) : result << val }
9
+ rescue ::StopIteration
10
+ nil
11
+ end
12
+ end
13
+ end
14
+
15
+ def self.eternity
16
+ from(Date.new(1970))
17
+ end
18
+
19
+ def self.from(date)
20
+ RecurringDate::Enumerator.new(infinity(date))
21
+ end
22
+
23
+ def yday(*args)
24
+ matching(*args, &:yday)
25
+ end
26
+
27
+ def mday(*args)
28
+ matching(*args, &:mday)
29
+ end
30
+
31
+ def wday(*args)
32
+ matching(*args, &:wday)
33
+ end
34
+
35
+ def mweek(*args)
36
+ matching(*args, &:mweek)
37
+ end
38
+
39
+ def month(*args)
40
+ matching(*args, &:month)
41
+ end
42
+
43
+ def year(*args)
44
+ matching(*args, &:year)
45
+ end
46
+
47
+ def not_yday(*args)
48
+ not_matching(*args, &:yday)
49
+ end
50
+
51
+ def not_mday(*args)
52
+ not_matching(*args, &:mday)
53
+ end
54
+
55
+ def not_wday(*args)
56
+ not_matching(*args, &:wday)
57
+ end
58
+
59
+ def not_mweek(*args)
60
+ not_matching(*args, &:mweek)
61
+ end
62
+
63
+ def not_month(*args)
64
+ not_matching(*args, &:month)
65
+ end
66
+
67
+ def not_year(*args)
68
+ not_matching(*args, &:year)
69
+ end
70
+
71
+ def matching(*args)
72
+ select { |date| args.include?(yield(date)) }
73
+ end
74
+
75
+ def not_matching(*args)
76
+ reject { |date| args.include?(yield(date)) }
77
+ end
78
+
79
+ def pattern(*args)
80
+ select_with_index do |_, i|
81
+ args.any? { |arg| ((i + 1) % arg).zero? }
82
+ end
83
+ end
84
+
85
+ def until(arg)
86
+ take_while { |date| date <= arg.to_date }
87
+ end
88
+
89
+ def select_with_index
90
+ index = 0
91
+ RecurringDate::Enumerator.new(self) do |result, value|
92
+ result << value if yield(value, index)
93
+ index += 1
94
+ end
95
+ end
96
+
97
+ def select
98
+ RecurringDate::Enumerator.new(self) { |result, value| result << value if yield(value) }
99
+ end
100
+
101
+ def reject
102
+ RecurringDate::Enumerator.new(self) { |result, value| result << value unless yield(value) }
103
+ end
104
+
105
+ def take(n)
106
+ taken = n
107
+ RecurringDate::Enumerator.new(self) do |result, value|
108
+ raise ::StopIteration if taken.zero?
109
+ result << value
110
+ taken -= 1
111
+ end
112
+ end
113
+
114
+ def take_while
115
+ RecurringDate::Enumerator.new(self) do |result, value|
116
+ raise ::StopIteration unless yield(value)
117
+ result << value
118
+ end
119
+ end
120
+
121
+ def inspect
122
+ ['#<RecurringDate::Enumerator:0x', object_id, '>'].join
123
+ end
124
+
125
+ def self.infinity(date)
126
+ ::Enumerator.new do |y|
127
+ i = date.prev_day
128
+ loop { y << (i = i.next) }
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,3 @@
1
+ module RecurringDate
2
+ VERSION = '0.1.1'.freeze
3
+ end
@@ -1,4 +1,4 @@
1
- require_relative 'recurring_date_enumerator'
1
+ require 'recurring_date/enumerator'
2
2
 
3
3
  module RecurringDate
4
4
  def mweek
@@ -6,7 +6,7 @@ module RecurringDate
6
6
  end
7
7
 
8
8
  def to_enum
9
- RecurringDateEnumerator.eternity(from: self)
9
+ RecurringDate::Enumerator.from(self)
10
10
  end
11
11
  end
12
12
 
@@ -0,0 +1,31 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'recurring_date/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'recurring_date'
7
+ spec.version = RecurringDate::VERSION
8
+ spec.authors = ['Paweł Placzyński']
9
+ spec.email = ['placzynski.pawel@gmail.com']
10
+
11
+ spec.summary = %q{Dates enumerator with conditions}
12
+ spec.description = %q{Iterate over a set of dates, giving an iteration conditions.}
13
+ spec.homepage = 'https://gitlab.binarapps.com/placek/recurring_date'
14
+
15
+ if spec.respond_to?(:metadata)
16
+ spec.metadata['homepage_uri'] = spec.homepage
17
+ spec.metadata['source_code_uri'] = 'https://gitlab.binarapps.com/placek/recurring_date'
18
+ else
19
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
20
+ end
21
+
22
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+
26
+ spec.require_paths = ['lib']
27
+
28
+ spec.add_development_dependency 'bundler', '~> 1.17'
29
+ spec.add_development_dependency 'rake', '~> 10.0'
30
+ spec.add_development_dependency 'rspec', '~> 3.0'
31
+ end
metadata CHANGED
@@ -1,31 +1,86 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: recurring_date
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
- - Paweł Placzyński
7
+ - Paweł Placzyński
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-01 00:00:00.000000000 Z
12
- dependencies: []
13
- description: Enumerator for recurring dates with specific patterns
11
+ date: 2020-03-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.17'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: Iterate over a set of dates, giving an iteration conditions.
14
56
  email:
15
- - should@not-fail.pl
16
- - p.placzynski@binarapps.com
17
57
  - placzynski.pawel@gmail.com
18
- - silquenarmo@gmail.com
19
58
  executables: []
20
59
  extensions: []
21
60
  extra_rdoc_files: []
22
61
  files:
62
+ - ".gitignore"
63
+ - ".gitlab-ci.yml"
64
+ - ".rspec"
65
+ - ".rubocop.yml"
66
+ - ".ruby-gemset"
67
+ - ".ruby-version"
68
+ - Gemfile
69
+ - Gemfile.lock
70
+ - LICENSE
71
+ - README.md
72
+ - Rakefile
73
+ - bin/console
74
+ - bin/setup
23
75
  - lib/recurring_date.rb
24
- - lib/recurring_date_enumerator.rb
25
- homepage: ''
26
- licenses:
27
- - MIT
28
- metadata: {}
76
+ - lib/recurring_date/enumerator.rb
77
+ - lib/recurring_date/version.rb
78
+ - recurring_date.gemspec
79
+ homepage: https://gitlab.binarapps.com/placek/recurring_date
80
+ licenses: []
81
+ metadata:
82
+ homepage_uri: https://gitlab.binarapps.com/placek/recurring_date
83
+ source_code_uri: https://gitlab.binarapps.com/placek/recurring_date
29
84
  post_install_message:
30
85
  rdoc_options: []
31
86
  require_paths:
@@ -41,9 +96,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
41
96
  - !ruby/object:Gem::Version
42
97
  version: '0'
43
98
  requirements: []
44
- rubyforge_project:
45
- rubygems_version: 2.6.11
99
+ rubygems_version: 3.0.6
46
100
  signing_key:
47
101
  specification_version: 4
48
- summary: Recurring dates enumerator
102
+ summary: Dates enumerator with conditions
49
103
  test_files: []
@@ -1,128 +0,0 @@
1
- require 'date'
2
-
3
- class RecurringDateEnumerator < Enumerator
4
- def initialize(range)
5
- super() do |result|
6
- begin
7
- range.each { |val| block_given? ? yield(result, val) : result << val }
8
- rescue StopIteration
9
- nil
10
- end
11
- end
12
- end
13
-
14
- def self.eternity(from: Date.new(1970))
15
- RecurringDateEnumerator.new(infinity(from))
16
- end
17
-
18
- def yday(*args)
19
- matching(*args, &:yday)
20
- end
21
-
22
- def mday(*args)
23
- matching(*args, &:mday)
24
- end
25
-
26
- def wday(*args)
27
- matching(*args, &:wday)
28
- end
29
-
30
- def mweek(*args)
31
- matching(*args, &:mweek)
32
- end
33
-
34
- def month(*args)
35
- matching(*args, &:month)
36
- end
37
-
38
- def year(*args)
39
- matching(*args, &:year)
40
- end
41
-
42
- def not_yday(*args)
43
- not_matching(*args, &:yday)
44
- end
45
-
46
- def not_mday(*args)
47
- not_matching(*args, &:mday)
48
- end
49
-
50
- def not_wday(*args)
51
- not_matching(*args, &:wday)
52
- end
53
-
54
- def not_mweek(*args)
55
- not_matching(*args, &:mweek)
56
- end
57
-
58
- def not_month(*args)
59
- not_matching(*args, &:month)
60
- end
61
-
62
- def not_year(*args)
63
- not_matching(*args, &:year)
64
- end
65
-
66
- def matching(*args)
67
- select { |date| args.include?(yield(date)) }
68
- end
69
-
70
- def not_matching(*args)
71
- reject { |date| args.include?(yield(date)) }
72
- end
73
-
74
- def pattern(*args)
75
- select_with_index do |_, i|
76
- args.any? do |arg|
77
- ((i + 1) % arg).zero?
78
- end
79
- end
80
- end
81
-
82
- def until(arg)
83
- take_while { |date| date <= arg.to_date }
84
- end
85
-
86
- def select_with_index
87
- index = 0
88
- RecurringDateEnumerator.new(self) do |result, value|
89
- result << value if yield(value, index)
90
- index += 1
91
- end
92
- end
93
-
94
- def select
95
- RecurringDateEnumerator.new(self) { |result, value| result << value if yield(value) }
96
- end
97
-
98
- def reject
99
- RecurringDateEnumerator.new(self) { |result, value| result << value unless yield(value) }
100
- end
101
-
102
- def take(n)
103
- taken = n
104
- RecurringDateEnumerator.new(self) do |result, value|
105
- raise StopIteration if taken.zero?
106
- result << value
107
- taken -= 1
108
- end
109
- end
110
-
111
- def take_while
112
- RecurringDateEnumerator.new(self) do |result, value|
113
- raise StopIteration unless yield(value)
114
- result << value
115
- end
116
- end
117
-
118
- def inspect
119
- ['#<RecurringDateEnumerator: 0x', object_id, '>'].join
120
- end
121
-
122
- def self.infinity(date)
123
- Enumerator.new do |y|
124
- i = date.prev_day
125
- loop { y << (i = i.next) }
126
- end
127
- end
128
- end