rrule 0.5.0 → 0.6.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: 102a445f4ce73b7678d2ba5ce981dd97265cd96eaba985a1a88fc65bef7dd6f5
4
- data.tar.gz: 436d7cf84a7e8673e3909a6b0dc6b629c348ca1b0a2df83b133201e7e46413b0
3
+ metadata.gz: ad88610152ac491684d813f22ced6298dd37075b43c0832bf5ddea6b722e5906
4
+ data.tar.gz: 8c18b1a8f5244cefe797e77a73fd6717cd0e4e754b7858045e2480c24a0d4a12
5
5
  SHA512:
6
- metadata.gz: 6b59c32ff4f679d3f7d1e8944b87e460d1a2ea5aa0bd7c38d3039cd62fb60af56dbc41e23eef63b42add7c3136e4af4ab62ef166e1c1cb643cff89e9a4784d9c
7
- data.tar.gz: 8040ef1e6d6c127e33352032e0bb146a46a1ba22c01237fac1a14343bac6f751803cd2582ec7058dd1d32cf0e319aa8e439be5f312ff189a755b28c48efaa985
6
+ metadata.gz: 97d4c45d2cc25a7624f4b237b8b309d878f27cff652e2f45b50141d57b2273da3b715f1f967e6885e2b669904e8e748bd2f09c34c9aa91d6b03ca759c567f387
7
+ data.tar.gz: fa4a974eb0acd3244232acafaf97a3220e2539673da54efcc116f6042272919805828a9b7aff3668675f25d22f295e21ac172764a085f4e1ea0749c35770c489
@@ -0,0 +1,41 @@
1
+ on:
2
+ pull_request:
3
+ push:
4
+ branches:
5
+ - master
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ ruby:
13
+ - 3.0.0
14
+ - 3.1.0
15
+ - 3.2.0
16
+ - 3.3.0
17
+ gemfile:
18
+ - gemfiles/activesupport_6_1.gemfile
19
+ - gemfiles/activesupport_7_0.gemfile
20
+ - gemfiles/activesupport_7_1.gemfile
21
+
22
+ name: Ruby ${{ matrix.ruby }} using Gemfile ${{ matrix.gemfile }}
23
+ env:
24
+ BUNDLE_GEMFILE: ${{ matrix.gemfile }}
25
+ steps:
26
+ - uses: actions/checkout@v3
27
+ - uses: ruby/setup-ruby@v1
28
+ with:
29
+ ruby-version: ${{ matrix.ruby }}
30
+ - name: 'Update gem command'
31
+ run: yes | gem update --system --force
32
+ - name: 'Update Bundler'
33
+ run: gem install bundler
34
+ - uses: actions/cache@v2
35
+ with:
36
+ path: vendor/bundle
37
+ key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
38
+ restore-keys: |
39
+ ${{ runner.os }}-gems-
40
+ - run: bundle install
41
+ - run: bundle exec rake
data/.rubocop.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.6
3
+ NewCops: disable
3
4
  Exclude:
4
5
  - 'gemfiles/**/*'
5
6
  - Appraisals
data/CHANGELOG.md CHANGED
@@ -1,9 +1,30 @@
1
1
  Change Log
2
2
  ==========
3
3
 
4
+ Version 0.6.0 *(2024-03-07)*
5
+ ----------------------------
6
+ ## What's Changed
7
+ * Test support for Ruby 3.1 by @rmitchell-sq in https://github.com/square/ruby-rrule/pull/43
8
+ * Rule#between didn't work when `limit` was provided by @edruder in https://github.com/square/ruby-rrule/pull/44
9
+ * Added Rule#from by @edruder in https://github.com/square/ruby-rrule/pull/45
10
+ * Added Rule#to_s by @Andy9822 in https://github.com/square/ruby-rrule/pull/50
11
+ * Implement `RRule::Rule#humanize` by @craigmcnamara in https://github.com/square/ruby-rrule/pull/49
12
+ * Update missing documentation for version 0.5.0 by @rmitchell-sq in https://github.com/square/ruby-rrule/pull/53
13
+ * Pivot from Travis CI to GitHub Actions by @leoarnold in https://github.com/square/ruby-rrule/pull/48
14
+ * Updating supported Rubies to add new versions and remove EOL ones by @rmitchell-sq in https://github.com/square/ruby-rrule/pull/56
15
+ * Implement `RRule::Rule#is_finite?` by @bahriddin in https://github.com/square/ruby-rrule/pull/55
16
+
17
+ ## New Contributors
18
+ * @edruder made their first contribution in https://github.com/square/ruby-rrule/pull/44
19
+ * @Andy9822 made their first contribution in https://github.com/square/ruby-rrule/pull/50
20
+ * @craigmcnamara made their first contribution in https://github.com/square/ruby-rrule/pull/49
21
+ * @bahriddin made their first contribution in https://github.com/square/ruby-rrule/pull/55
22
+
23
+ **Full Changelog**: https://github.com/square/ruby-rrule/compare/v0.4.4...v0.5.1
24
+
4
25
  Version 0.5.0 *(2022-03-14)*
5
26
  ----------------------------
6
- Add #from method to Rule object
27
+ Added `#from` method. Added test support for Ruby 3.1. Fixed bug in `#between` method when `limit` was provided.
7
28
 
8
29
  Version 0.4.4 *(2022-03-01)*
9
30
  ----------------------------
data/Gemfile CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- gem 'pry', '~> 0.12.2'
5
+ gem 'pry', '~> 0.14.1'
6
6
  gem 'rake'
7
7
  gem 'rspec', '~> 3.8'
8
8
  gem 'rubocop', '0.63.1'
9
9
 
10
10
  platform :mri do
11
- gem 'pry-byebug'
11
+ gem 'pry-byebug', '~> 3.10.1'
12
12
  end
13
13
 
14
14
  gemspec
data/README.md CHANGED
@@ -30,6 +30,16 @@ rrule.between(Time.new(2016, 6, 23), Time.new(2016, 6, 24))
30
30
  => [2016-06-23 16:45:32 -0700]
31
31
  ```
32
32
 
33
+ You can generate all instances starting from a specified date with the `#from` method:
34
+
35
+ ```ruby
36
+ rrule = RRule::Rule.new('FREQ=DAILY;COUNT=3', dtstart: Time.new(2016, 1, 1))
37
+ rrule.all
38
+ => [2016-01-01 16:45:32 -0700, 2016-01-02 16:45:32 -0700, 2016-01-03 16:45:32 -0700]
39
+ rrule.from(Time.new(2016, 1, 2))
40
+ => [2016-01-02 16:45:32 -0700, 2016-01-03 16:45:32 -0700]
41
+ ```
42
+
33
43
  You can limit the number of instances that are returned with the `limit` option:
34
44
 
35
45
  ```ruby
@@ -2,11 +2,11 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "pry", "~> 0.12.2"
5
+ gem "pry", "~> 0.14.1"
6
6
  gem "rake"
7
7
  gem "rspec", "~> 3.8"
8
8
  gem "rubocop", "0.63.1"
9
- gem "activesupport", "~> 5"
9
+ gem "activesupport", "~> 6.1"
10
10
 
11
11
  platforms :mri do
12
12
  gem "pry-byebug"
@@ -2,11 +2,11 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "pry", "~> 0.12.2"
5
+ gem "pry", "~> 0.14.1"
6
6
  gem "rake"
7
7
  gem "rspec", "~> 3.8"
8
8
  gem "rubocop", "0.63.1"
9
- gem "activesupport", "~> 6"
9
+ gem "activesupport", "~> 7.0"
10
10
 
11
11
  platforms :mri do
12
12
  gem "pry-byebug"
@@ -2,11 +2,11 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "pry", "~> 0.12.2"
5
+ gem "pry", "~> 0.14.1"
6
6
  gem "rake"
7
7
  gem "rspec", "~> 3.8"
8
8
  gem "rubocop", "0.63.1"
9
- gem "activesupport", "~> 7"
9
+ gem "activesupport", "~> 7.1"
10
10
 
11
11
  platforms :mri do
12
12
  gem "pry-byebug"
data/lib/rrule/context.rb CHANGED
@@ -17,7 +17,9 @@ module RRule
17
17
 
18
18
  if options[:bynweekday] && !options[:bynweekday].empty? && (month != last_month || year != last_year)
19
19
  possible_date_ranges = []
20
- if options[:freq] == 'YEARLY'
20
+
21
+ case options[:freq]
22
+ when 'YEARLY'
21
23
  if options[:bymonth]
22
24
  options[:bymonth].each do |mon|
23
25
  possible_date_ranges.push(elapsed_days_in_year_by_month[(mon - 1)..mon])
@@ -25,7 +27,7 @@ module RRule
25
27
  else
26
28
  possible_date_ranges = [[0, year_length_in_days]]
27
29
  end
28
- elsif options[:freq] == 'MONTHLY'
30
+ when 'MONTHLY'
29
31
  possible_date_ranges = [elapsed_days_in_year_by_month[(month - 1)..month]]
30
32
  end
31
33
 
@@ -0,0 +1,214 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RRule
4
+ # Based off https://github.com/jakubroztocil/rrule/blob/master/src/nlp/totext.ts
5
+ #
6
+ class Humanizer
7
+ attr_reader :rrule, :options
8
+
9
+ OPTION_ATTRIBUTE_RE = /_option/.freeze
10
+
11
+ DAY_NAMES = %w[
12
+ Sunday
13
+ Monday
14
+ Tuesday
15
+ Wednesday
16
+ Thursday
17
+ Friday
18
+ Saturday
19
+ ].freeze
20
+
21
+ def initialize(rrule, options)
22
+ @rrule = rrule
23
+ @options = options
24
+
25
+ # Define instance method for each of the options.
26
+ options.each { |name, value| define_singleton_method("#{name}_option") { value } }
27
+ end
28
+
29
+ def to_s
30
+ @buffer = 'every'
31
+
32
+ send freq_option.downcase
33
+
34
+ raise 'Implement Until' if until_option
35
+ if count_option
36
+ add 'for'
37
+ add count_option
38
+ add plural?(count_option) ? 'times' : 'time'
39
+ end
40
+
41
+ @buffer
42
+ end
43
+
44
+ # Return nil if we're trying to access an option that isn't present.
45
+ def method_missing(method_name, *args)
46
+ if method_name.to_s.match?(OPTION_ATTRIBUTE_RE)
47
+ nil
48
+ else
49
+ super
50
+ end
51
+ end
52
+
53
+ def respond_to_missing?(method_name)
54
+ super || method_name.to_s.match?(OPTION_ATTRIBUTE_RE)
55
+ end
56
+
57
+ protected
58
+
59
+ def list(arr, formatter, final_delimiter = nil, delimiter: ',')
60
+ *rest, middle, tail = arr.map(&formatter)
61
+
62
+ if final_delimiter
63
+ [*rest, [middle, tail].compact.join(" #{final_delimiter} ")].join("#{delimiter} ")
64
+ else
65
+ [*rest, middle, tail].compact.join("#{delimiter} ")
66
+ end
67
+ end
68
+
69
+ def add(string)
70
+ @buffer += " #{string}"
71
+ end
72
+
73
+ def plural?(num)
74
+ num.to_i % 100 != 1
75
+ end
76
+
77
+ def daily
78
+ add interval_option if interval_option != 1
79
+
80
+ if byweekday_option && weekdays?
81
+ add plural?(interval_option) ? 'weekdays' : 'weekday'
82
+ else
83
+ add plural?(interval_option) ? 'days' : 'day'
84
+ end
85
+
86
+ if bymonth_option
87
+ add 'in'
88
+ _bymonth
89
+ end
90
+
91
+ if bymonthday_option
92
+ _bymonthday
93
+ elsif byweekday_option
94
+ _byweekday
95
+ elsif byhour_option
96
+ _byhour
97
+ end
98
+ end
99
+
100
+ def weekly
101
+ if interval_option != 1
102
+ add interval_option
103
+ add plural?(interval_option) ? 'weeks' : 'week'
104
+ end
105
+
106
+ if byweekday_option && weekdays?
107
+ if interval_option == 1
108
+ add plural?(interval_option) ? 'weekdays' : 'weekday'
109
+ else
110
+ add 'on'
111
+ add 'weekdays'
112
+ end
113
+ elsif byweekday_option && every_day?
114
+ add plural?(interval_option) ? 'days' : 'day'
115
+ else
116
+ add 'week' if interval_option == 1
117
+
118
+ if bymonth_option
119
+ add 'in'
120
+ _bymonth
121
+ end
122
+
123
+ if bymonthday_option
124
+ _bymonthday
125
+ elsif byweekday_option
126
+ _byweekday
127
+ end
128
+ end
129
+ end
130
+
131
+ def monthly
132
+ if bymonth_option
133
+ if interval_option != 1
134
+ add interval_option
135
+ add 'months'
136
+ add 'in' if plural?(interval_option)
137
+ end
138
+
139
+ _bymonth
140
+ else
141
+ add interval_option if interval_option != 1
142
+
143
+ add plural?(interval_option) ? 'months' : 'month'
144
+ end
145
+
146
+ if bymonthday_option
147
+ _bymonthday
148
+ elsif byweekday_option && weekdays?
149
+ add 'on'
150
+ add 'weekdays'
151
+ elsif byweekday_option || bynweekday_option
152
+ _byweekday
153
+ end
154
+ end
155
+
156
+ def weekdaytext(day)
157
+ [day.ordinal && nth(day.ordinal), DAY_NAMES[day.index]].compact.join(' ')
158
+ end
159
+
160
+ def all_weeks?
161
+ bynweekday_option.all? { |option| option.ordinal.nil? }
162
+ end
163
+
164
+ def every_day?
165
+ byweekday_option.sort_by(&:index).map { |day| WEEKDAYS[day.index]} == RRule::WEEKDAYS
166
+ end
167
+
168
+ def weekdays?
169
+ return false if byweekday_option.none?
170
+
171
+ byweekday_option.sort_by(&:index).map { |day| WEEKDAYS[day.index]} == RRule::WEEKDAYS - %w[SA SU]
172
+ end
173
+
174
+ def _bymonth
175
+ add list(this.options.bymonth, method(:monthtext), 'and')
176
+ end
177
+
178
+ def _byweekday
179
+ if byweekday_option.any?
180
+ add 'on'
181
+ add list(byweekday_option, method(:weekdaytext))
182
+ end
183
+
184
+ return unless bynweekday_option.any?
185
+
186
+ add 'and' if all_weeks?
187
+ add 'on the'
188
+ add list(bynweekday_option, method(:weekdaytext), 'and')
189
+ end
190
+
191
+ def _byhour
192
+ add 'at'
193
+ add list byhour_option, :to_s, 'and'
194
+ end
195
+
196
+ def nth(ordinal)
197
+ return 'last' if ordinal == -1
198
+
199
+ nth =
200
+ case npos = ordinal.abs
201
+ when 1, 21, 31
202
+ "#{npos}st"
203
+ when 2, 22
204
+ "#{npos}nd"
205
+ when 3, 23
206
+ "#{npos}rd"
207
+ else
208
+ "#{npos}th"
209
+ end
210
+
211
+ ordinal < 0 ? "#{nth} last" : nth
212
+ end
213
+ end
214
+ end
data/lib/rrule/rule.rb CHANGED
@@ -8,6 +8,7 @@ module RRule
8
8
 
9
9
  def initialize(rrule, dtstart: Time.now, tzid: 'UTC', exdate: [], max_year: nil)
10
10
  @tz = tzid
11
+ @rrule = rrule
11
12
  @dtstart = dtstart.is_a?(Date) ? dtstart : floor_to_seconds_in_timezone(dtstart)
12
13
  @exdate = exdate
13
14
  @options = parse_options(rrule)
@@ -16,6 +17,10 @@ module RRule
16
17
  @max_date = DateTime.new(@max_year)
17
18
  end
18
19
 
20
+ def to_s
21
+ @rrule
22
+ end
23
+
19
24
  def all(limit: nil)
20
25
  all_until(limit: limit)
21
26
  end
@@ -78,6 +83,15 @@ module RRule
78
83
  enumerator.next
79
84
  end
80
85
 
86
+ def humanize
87
+ Humanizer.new(self, options).to_s
88
+ end
89
+
90
+ def is_finite?
91
+ keys = %i[count until] & options.keys
92
+ !keys.empty?
93
+ end
94
+
81
95
  private
82
96
 
83
97
  attr_reader :options, :max_year, :max_date, :frequency_type
data/lib/rrule/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RRule
4
- VERSION = '0.5.0'
4
+ VERSION = '0.6.0'
5
5
  end
data/lib/rrule/weekday.rb CHANGED
@@ -12,7 +12,7 @@ module RRule
12
12
  def self.parse(weekday)
13
13
  match = /([+-]?\d+)?([A-Z]{2})/.match(weekday)
14
14
  index = RRule::WEEKDAYS.index(match[2])
15
- ordinal = match[1] ? match[1].to_i : nil
15
+ ordinal = match[1]&.to_i
16
16
  new(index, ordinal)
17
17
  end
18
18
  end
data/lib/rrule.rb CHANGED
@@ -6,6 +6,7 @@ module RRule
6
6
  autoload :Rule, 'rrule/rule'
7
7
  autoload :Context, 'rrule/context'
8
8
  autoload :Weekday, 'rrule/weekday'
9
+ autoload :Humanizer, 'rrule/humanizer'
9
10
 
10
11
  autoload :Frequency, 'rrule/frequencies/frequency'
11
12
  autoload :Daily, 'rrule/frequencies/daily'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rrule
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Mitchell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-14 00:00:00.000000000 Z
11
+ date: 2024-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -44,9 +44,9 @@ executables: []
44
44
  extensions: []
45
45
  extra_rdoc_files: []
46
46
  files:
47
+ - ".github/workflows/test.yml"
47
48
  - ".gitignore"
48
49
  - ".rubocop.yml"
49
- - ".travis.yml"
50
50
  - Appraisals
51
51
  - CHANGELOG.md
52
52
  - CONTRIBUTING.md
@@ -54,12 +54,9 @@ files:
54
54
  - LICENSE.txt
55
55
  - README.md
56
56
  - Rakefile
57
- - gemfiles/activesupport_2.3_LTS.gemfile
58
- - gemfiles/activesupport_3.gemfile
59
- - gemfiles/activesupport_4.gemfile
60
- - gemfiles/activesupport_5.gemfile
61
- - gemfiles/activesupport_6.gemfile
62
- - gemfiles/activesupport_7.gemfile
57
+ - gemfiles/activesupport_6_1.gemfile
58
+ - gemfiles/activesupport_7_0.gemfile
59
+ - gemfiles/activesupport_7_1.gemfile
63
60
  - lib/rrule.rb
64
61
  - lib/rrule/context.rb
65
62
  - lib/rrule/filters/by_month.rb
@@ -76,6 +73,7 @@ files:
76
73
  - lib/rrule/generators/all_occurrences.rb
77
74
  - lib/rrule/generators/by_set_position.rb
78
75
  - lib/rrule/generators/generator.rb
76
+ - lib/rrule/humanizer.rb
79
77
  - lib/rrule/rule.rb
80
78
  - lib/rrule/version.rb
81
79
  - lib/rrule/weekday.rb
@@ -104,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
102
  - !ruby/object:Gem::Version
105
103
  version: '0'
106
104
  requirements: []
107
- rubygems_version: 3.1.6
105
+ rubygems_version: 3.2.33
108
106
  signing_key:
109
107
  specification_version: 4
110
108
  summary: RRule expansion
data/.travis.yml DELETED
@@ -1,36 +0,0 @@
1
- language: ruby
2
- sudo: false
3
- rvm:
4
- - 2.6.5
5
- - 2.7.0
6
- - 3.0.0
7
- - 3.1.0
8
-
9
- gemfile:
10
- - gemfiles/activesupport_2.3_LTS.gemfile
11
- - gemfiles/activesupport_3.gemfile
12
- - gemfiles/activesupport_4.gemfile
13
- - gemfiles/activesupport_5.gemfile
14
- - gemfiles/activesupport_6.gemfile
15
- - gemfiles/activesupport_7.gemfile
16
-
17
- jobs:
18
- exclude:
19
- - rvm: 2.6.5
20
- gemfile: gemfiles/activesupport_7.gemfile
21
- - rvm: 2.7.0
22
- gemfile: gemfiles/activesupport_3.gemfile
23
- - rvm: 2.7.0
24
- gemfile: gemfiles/activesupport_4.gemfile
25
- - rvm: 3.0.0
26
- gemfile: gemfiles/activesupport_3.gemfile
27
- - rvm: 3.0.0
28
- gemfile: gemfiles/activesupport_4.gemfile
29
- - rvm: 3.1.0
30
- gemfile: gemfiles/activesupport_3.gemfile
31
- - rvm: 3.1.0
32
- gemfile: gemfiles/activesupport_4.gemfile
33
-
34
- before_install:
35
- - yes | gem update --system --force
36
- - gem install bundler
@@ -1,16 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "pry", "~> 0.12.2"
6
- gem "rake"
7
- gem "rspec", "~> 3.8"
8
- gem "rubocop", "0.63.1"
9
- gem "rexml"
10
- gem "activesupport", ">= 2", git: "https://github.com/makandra/rails.git", branch: "2-3-lts"
11
-
12
- platforms :mri do
13
- gem "pry-byebug"
14
- end
15
-
16
- gemspec path: "../"
@@ -1,16 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "pry", "~> 0.12.2"
6
- gem "rake"
7
- gem "rspec", "~> 3.8"
8
- gem "rubocop", "0.63.1"
9
- gem "activesupport", "~> 3"
10
- gem "tzinfo", "~> 1.2"
11
-
12
- platforms :mri do
13
- gem "pry-byebug"
14
- end
15
-
16
- gemspec path: "../"
@@ -1,15 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "pry", "~> 0.12.2"
6
- gem "rake"
7
- gem "rspec", "~> 3.8"
8
- gem "rubocop", "0.63.1"
9
- gem "activesupport", "~> 4"
10
-
11
- platforms :mri do
12
- gem "pry-byebug"
13
- end
14
-
15
- gemspec path: "../"