rrule 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +25 -0
  4. data/.travis.yml +6 -1
  5. data/Gemfile +9 -0
  6. data/Rakefile +9 -3
  7. data/lib/rrule.rb +4 -0
  8. data/lib/rrule/context.rb +5 -3
  9. data/lib/rrule/filters/by_month.rb +2 -0
  10. data/lib/rrule/filters/by_month_day.rb +2 -0
  11. data/lib/rrule/filters/by_week_day.rb +2 -0
  12. data/lib/rrule/filters/by_week_number.rb +2 -0
  13. data/lib/rrule/filters/by_year_day.rb +3 -1
  14. data/lib/rrule/frequencies/daily.rb +2 -0
  15. data/lib/rrule/frequencies/frequency.rb +4 -12
  16. data/lib/rrule/frequencies/monthly.rb +2 -0
  17. data/lib/rrule/frequencies/simple_weekly.rb +6 -6
  18. data/lib/rrule/frequencies/weekly.rb +2 -0
  19. data/lib/rrule/frequencies/yearly.rb +2 -0
  20. data/lib/rrule/generators/all_occurrences.rb +2 -0
  21. data/lib/rrule/generators/by_set_position.rb +2 -0
  22. data/lib/rrule/generators/generator.rb +3 -1
  23. data/lib/rrule/rule.rb +18 -33
  24. data/lib/rrule/version.rb +5 -0
  25. data/lib/rrule/weekday.rb +3 -1
  26. data/rrule.gemspec +16 -10
  27. data/scripts/benchmark.rb +3 -1
  28. metadata +13 -56
  29. data/spec/context_spec.rb +0 -261
  30. data/spec/filters/by_month_day_spec.rb +0 -35
  31. data/spec/filters/by_month_spec.rb +0 -35
  32. data/spec/filters/by_week_day_spec.rb +0 -35
  33. data/spec/filters/by_week_number_spec.rb +0 -41
  34. data/spec/filters/by_year_day_spec.rb +0 -35
  35. data/spec/frequencies/daily_spec.rb +0 -62
  36. data/spec/frequencies/monthly_spec.rb +0 -63
  37. data/spec/frequencies/simple_weekly_spec.rb +0 -32
  38. data/spec/frequencies/weekly_spec.rb +0 -92
  39. data/spec/frequencies/yearly_spec.rb +0 -54
  40. data/spec/generators/all_occurrences_spec.rb +0 -44
  41. data/spec/generators/by_set_position_spec.rb +0 -39
  42. data/spec/generators/generator_spec.rb +0 -110
  43. data/spec/rule_spec.rb +0 -2338
  44. data/spec/spec_helper.rb +0 -23
  45. data/spec/weekday_spec.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1aad8dd06524a47f1d310b7f077db21f41696bc7
4
- data.tar.gz: f2e1673c1fd07da16c47fc96e944eeabef43578b
2
+ SHA256:
3
+ metadata.gz: 110d8805d4e642767c86d7e23f0b77d8d42a0a11ef3c5edf5c08ee2d8f78d4ab
4
+ data.tar.gz: 8dcd49b64e8300b5facdfb92c72485b6c87b3003ba9dc87116fe13ca9bd44bf5
5
5
  SHA512:
6
- metadata.gz: fa77f6132a2d47a45d8aab0a58af68a1ccd0417e22a9c2fc6ef4a2b14aef90e65040324177893773cba2b06e74373776105a19e078c5d81360f5e894b2cdec3c
7
- data.tar.gz: 4fddc6b136db1d57c8d8e89fe099820e572f13fc447647cdd7c43942a74112255c8720ad2b8c82a0cb1586a8a1bdb0e862ec12014f6f05c5982a86ce58207518
6
+ metadata.gz: 467ad003c49dea6fb320775f59a33f739405edd0b330b87512ed4e183bcd757f8e16e4deda296c6f916055056ba98ae0be623df3f78fc9b8c39b790ca4198db6
7
+ data.tar.gz: c51e63c57919c57c4954b66c4b55d77ed6f513117a338ea76c595239433a1bc983c50706e642ba3b7b596aaf1feb3d111743ba8bd945c61d372f099656170dbb
data/.gitignore CHANGED
@@ -1,4 +1,6 @@
1
+ Gemfile.lock
1
2
  .rspec
2
3
  *.gem
3
4
  *.sublime-project
4
5
  *.sublime-workspace
6
+ Gemfile.lock
@@ -0,0 +1,25 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
4
+ Layout:
5
+ Enabled: false
6
+
7
+ Lint/NonLocalExitFromIterator:
8
+ Enabled: false
9
+
10
+ Metrics:
11
+ Enabled: false
12
+
13
+ Naming:
14
+ Enabled: false
15
+
16
+ Style/Documentation:
17
+ Enabled: false
18
+ Style/MultilineBlockChain:
19
+ Enabled: false
20
+ Style/NumericPredicate:
21
+ Enabled: false
22
+ Style/RescueModifier:
23
+ Enabled: false
24
+ Style/TrailingCommaInArrayLiteral:
25
+ EnforcedStyleForMultiline: comma
@@ -1,3 +1,8 @@
1
1
  language: ruby
2
+ sudo: false
2
3
  rvm:
3
- - 2.3.1
4
+ - 2.3.8
5
+ - 2.4.5
6
+ - 2.5.3
7
+ - 2.6.0
8
+ - ruby-head
data/Gemfile CHANGED
@@ -1,5 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
5
+ gem 'pry'
3
6
  gem 'rake'
7
+ gem 'rspec', '~> 3.8'
8
+ gem 'rubocop', '0.63.1'
9
+
10
+ platform :mri do
11
+ gem 'pry-byebug'
12
+ end
4
13
 
5
14
  gemspec
data/Rakefile CHANGED
@@ -1,12 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rubygems'
2
4
  require 'rake'
5
+ require 'bundler/gem_tasks'
3
6
  require 'rspec/core/rake_task'
4
- require File.expand_path('../lib/rrule', __FILE__)
7
+ require File.expand_path('lib/rrule', __dir__)
5
8
 
6
9
  RSpec::Core::RakeTask.new(:spec)
7
10
 
11
+ require 'rubocop/rake_task'
12
+ RuboCop::RakeTask.new
13
+
8
14
  namespace :spec do
9
- task :all => ['spec']
15
+ task all: ['spec']
10
16
  end
11
17
 
12
- task :default => 'spec:all'
18
+ task default: %w[spec:all rubocop]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/all'
2
4
 
3
5
  module RRule
@@ -22,6 +24,8 @@ module RRule
22
24
  autoload :AllOccurrences, 'rrule/generators/all_occurrences'
23
25
  autoload :BySetPosition, 'rrule/generators/by_set_position'
24
26
 
27
+ WEEKDAYS = %w[SU MO TU WE TH FR SA].freeze
28
+
25
29
  def self.parse(rrule, **options)
26
30
  Rule.new(rrule, **options)
27
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class Context
3
5
  attr_reader :options, :dtstart, :tz, :day_of_year_mask, :year
@@ -17,14 +19,14 @@ module RRule
17
19
  possible_date_ranges = []
18
20
  if options[:freq] == 'YEARLY'
19
21
  if options[:bymonth]
20
- options[:bymonth].each do |month|
21
- possible_date_ranges.push(elapsed_days_in_year_by_month[(month - 1)..(month)])
22
+ options[:bymonth].each do |mon|
23
+ possible_date_ranges.push(elapsed_days_in_year_by_month[(mon - 1)..mon])
22
24
  end
23
25
  else
24
26
  possible_date_ranges = [[0, year_length_in_days]]
25
27
  end
26
28
  elsif options[:freq] == 'MONTHLY'
27
- possible_date_ranges = [elapsed_days_in_year_by_month[(month - 1)..(month)]]
29
+ possible_date_ranges = [elapsed_days_in_year_by_month[(month - 1)..month]]
28
30
  end
29
31
 
30
32
  unless possible_date_ranges.empty?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class ByMonth
3
5
  def initialize(by_months, context)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class ByMonthDay
3
5
  def initialize(by_month_days, context)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class ByWeekDay
3
5
  def initialize(weekdays, context)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class ByWeekNumber
3
5
  def initialize(by_week_numbers, context)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class ByYearDay
3
5
  def initialize(by_year_days, context)
@@ -6,7 +8,7 @@ module RRule
6
8
  end
7
9
 
8
10
  def reject?(i)
9
- !by_year_days.empty? &&
11
+ !by_year_days.empty? &&
10
12
  ((i < context.year_length_in_days && !by_year_days.include?(i + 1) && !by_year_days.include?(i - context.year_length_in_days)) ||
11
13
  (i >= context.year_length_in_days && !by_year_days.include?(i + 1 - context.year_length_in_days) && !by_year_days.include?(i - context.year_length_in_days - context.next_year_length_in_days)))
12
14
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class Daily < Frequency
3
5
  def possible_days
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class Frequency
3
5
  attr_reader :current_date, :filters, :generator, :timeset
@@ -12,9 +14,7 @@ module RRule
12
14
 
13
15
  def advance
14
16
  @current_date = current_date.advance(advance_by).tap do |new_date|
15
- unless same_month(current_date, new_date)
16
- context.rebuild(new_date.year, new_date.month)
17
- end
17
+ context.rebuild(new_date.year, new_date.month) unless same_month(current_date, new_date)
18
18
  end
19
19
  end
20
20
 
@@ -32,10 +32,6 @@ module RRule
32
32
  end
33
33
  end
34
34
 
35
- def possible_days
36
- fail NotImplementedError
37
- end
38
-
39
35
  def self.for_options(options)
40
36
  case options[:freq]
41
37
  when 'DAILY'
@@ -51,7 +47,7 @@ module RRule
51
47
  when 'YEARLY'
52
48
  Yearly
53
49
  else
54
- raise InvalidRRule, "Valid FREQ value is required"
50
+ raise InvalidRRule, 'Valid FREQ value is required'
55
51
  end
56
52
  end
57
53
 
@@ -62,9 +58,5 @@ module RRule
62
58
  def same_month(first_date, second_date)
63
59
  first_date.month == second_date.month && first_date.year == second_date.year
64
60
  end
65
-
66
- def advance_by
67
- fail NotImplementedError
68
- end
69
61
  end
70
62
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class Monthly < Frequency
3
5
  def possible_days
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class SimpleWeekly < Frequency
3
5
  def next_occurrences
@@ -8,15 +10,13 @@ module RRule
8
10
  end
9
11
 
10
12
  def correct_current_date_if_needed
11
- if context.options[:byweekday].present?
12
- target_wday = context.options[:byweekday].first.index
13
+ target_wday = if context.options[:byweekday].present?
14
+ context.options[:byweekday].first.index
13
15
  else
14
- target_wday = context.dtstart.wday
16
+ context.dtstart.wday
15
17
  end
16
18
 
17
- while @current_date.wday != target_wday
18
- @current_date = @current_date + 1.day
19
- end
19
+ @current_date += 1.day while @current_date.wday != target_wday
20
20
  end
21
21
  end
22
22
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class Weekly < Frequency
3
5
  def possible_days
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class Yearly < Frequency
3
5
  def possible_days
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class AllOccurrences < Generator
3
5
  def combine_dates_and_times(dayset, timeset)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class BySetPosition < Generator
3
5
  attr_reader :by_set_positions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class Generator
3
5
  attr_reader :context
@@ -31,4 +33,4 @@ module RRule
31
33
  end.flatten
32
34
  end
33
35
  end
34
- end
36
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class Rule
3
5
  include Enumerable
@@ -25,11 +27,8 @@ module RRule
25
27
  end
26
28
 
27
29
  def each(floor_date: nil)
28
- floor_date ||= dtstart
29
30
  # If we have a COUNT or INTERVAL option, we have to start at dtstart, because those are relative to dtstart
30
- if count_or_interval_present?
31
- floor_date = dtstart
32
- end
31
+ floor_date = dtstart if count_or_interval_present? || floor_date.nil? || dtstart > floor_date
33
32
 
34
33
  return enum_for(:each, floor_date: floor_date) unless block_given?
35
34
  context = Context.new(options, dtstart, tz)
@@ -39,30 +38,20 @@ module RRule
39
38
  count = options[:count]
40
39
 
41
40
  filters = []
42
- if options[:bymonth]
43
- filters.push(ByMonth.new(options[:bymonth], context))
44
- end
41
+ filters.push(ByMonth.new(options[:bymonth], context)) if options[:bymonth]
45
42
 
46
- if options[:byweekno]
47
- filters.push(ByWeekNumber.new(options[:byweekno], context))
48
- end
43
+ filters.push(ByWeekNumber.new(options[:byweekno], context)) if options[:byweekno]
49
44
 
50
- if options[:byweekday]
51
- filters.push(ByWeekDay.new(options[:byweekday], context))
52
- end
45
+ filters.push(ByWeekDay.new(options[:byweekday], context)) if options[:byweekday]
53
46
 
54
- if options[:byyearday]
55
- filters.push(ByYearDay.new(options[:byyearday], context))
56
- end
47
+ filters.push(ByYearDay.new(options[:byyearday], context)) if options[:byyearday]
57
48
 
58
- if options[:bymonthday]
59
- filters.push(ByMonthDay.new(options[:bymonthday], context))
60
- end
49
+ filters.push(ByMonthDay.new(options[:bymonthday], context)) if options[:bymonthday]
61
50
 
62
- if options[:bysetpos]
63
- generator = BySetPosition.new(options[:bysetpos], context)
51
+ generator = if options[:bysetpos]
52
+ BySetPosition.new(options[:bysetpos], context)
64
53
  else
65
- generator = AllOccurrences.new(context)
54
+ AllOccurrences.new(context)
66
55
  end
67
56
 
68
57
  frequency = Frequency.for_options(options).new(context, filters, generator, timeset, start_date: floor_date)
@@ -117,15 +106,15 @@ module RRule
117
106
  i = begin
118
107
  Integer(value)
119
108
  rescue ArgumentError
120
- raise InvalidRRule, "COUNT must be a non-negative integer"
109
+ raise InvalidRRule, 'COUNT must be a non-negative integer'
121
110
  end
122
- raise InvalidRRule, "COUNT must be a non-negative integer" if i < 0
111
+ raise InvalidRRule, 'COUNT must be a non-negative integer' if i < 0
123
112
  options[:count] = i
124
113
  when 'UNTIL'
125
114
  options[:until] = Time.parse(value)
126
115
  when 'INTERVAL'
127
116
  i = Integer(value) rescue 0
128
- raise InvalidRRule, "INTERVAL must be a positive integer" unless i > 0
117
+ raise InvalidRRule, 'INTERVAL must be a positive integer' unless i > 0
129
118
  options[:interval] = i
130
119
  when 'BYHOUR'
131
120
  options[:byhour] = value.split(',').compact.map(&:to_i)
@@ -138,7 +127,7 @@ module RRule
138
127
  when 'BYSETPOS'
139
128
  options[:bysetpos] = value.split(',').map(&:to_i)
140
129
  when 'WKST'
141
- options[:wkst] = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'].index(value)
130
+ options[:wkst] = RRule::WEEKDAYS.index(value)
142
131
  when 'BYMONTH'
143
132
  options[:bymonth] = value.split(',').compact.map(&:to_i)
144
133
  when 'BYMONTHDAY'
@@ -150,12 +139,10 @@ module RRule
150
139
  end
151
140
  end
152
141
 
153
- if !(options[:byweekno] || options[:byyearday] || options[:bymonthday] || options[:byweekday])
142
+ unless options[:byweekno] || options[:byyearday] || options[:bymonthday] || options[:byweekday]
154
143
  case options[:freq]
155
144
  when 'YEARLY'
156
- unless options[:bymonth]
157
- options[:bymonth] = [dtstart.month]
158
- end
145
+ options[:bymonth] = [dtstart.month] unless options[:bymonth]
159
146
  options[:bymonthday] = [dtstart.day]
160
147
  when 'MONTHLY'
161
148
  options[:bymonthday] = [dtstart.day]
@@ -165,9 +152,7 @@ module RRule
165
152
  end
166
153
  end
167
154
 
168
- unless options[:byweekday].nil?
169
- options[:byweekday], options[:bynweekday] = options[:byweekday].partition { |wday| wday.ordinal.nil? }
170
- end
155
+ options[:byweekday], options[:bynweekday] = options[:byweekday].partition { |wday| wday.ordinal.nil? } unless options[:byweekday].nil?
171
156
 
172
157
  options[:timeset] = [{ hour: (options[:byhour].presence || dtstart.hour), minute: (options[:byminute].presence || dtstart.min), second: (options[:bysecond].presence || dtstart.sec) }]
173
158
 
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RRule
4
+ VERSION = '0.4.2'
5
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RRule
2
4
  class Weekday
3
5
  attr_reader :index, :ordinal
@@ -9,7 +11,7 @@ module RRule
9
11
 
10
12
  def self.parse(weekday)
11
13
  match = /([+-]?\d)?([A-Z]{2})/.match(weekday)
12
- index = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'].index(match[2])
14
+ index = RRule::WEEKDAYS.index(match[2])
13
15
  ordinal = match[1] ? match[1].to_i : nil
14
16
  new(index, ordinal)
15
17
  end
@@ -1,20 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'rrule/version'
6
+
1
7
  Gem::Specification.new do |s|
2
8
  s.name = 'rrule'
3
- s.version = '0.4.1'
4
- s.date = '2018-04-24'
9
+ s.version = RRule::VERSION
5
10
  s.summary = 'RRule expansion'
6
11
  s.description = 'A gem for expanding dates according to the RRule specification'
7
12
  s.authors = ['Ryan Mitchell']
8
13
  s.email = 'rmitchell@squareup.com'
9
- s.files = `git ls-files`.split($/)
10
- s.test_files = s.files.grep(%r{^(test|spec|features)/})
14
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
11
15
  s.require_paths = ['lib']
12
- s.homepage = 'http://rubygems.org/gems/rrule'
16
+ s.homepage = 'https://rubygems.org/gems/rrule'
17
+ s.metadata = {
18
+ 'homepage' => 'https://rubygems.org/gems/rrule',
19
+ 'source_code_uri' => 'https://github.com/square/ruby-rrule',
20
+ 'bug_tracker_uri' => 'https://github.com/square/ruby-rrule/issues',
21
+ 'changelog_uri' => 'https://github.com/square/ruby-rrule/blob/master/CHANGELOG.md'
22
+ }
13
23
 
14
- # Since Ruby 1.9.2, Time implementation uses a signed 63 bit integer, Bignum
15
- # or Rational. This enables Time to finally work with years after 2038 which
16
- # is critical for this library.
17
- s.required_ruby_version = '>= 1.9.2'
24
+ s.required_ruby_version = '>= 2.3.0'
18
25
  s.add_runtime_dependency 'activesupport', '>= 4.1'
19
- s.add_development_dependency 'rspec', '~> 3.4'
20
26
  end