rrule 0.4.1 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/.rubocop.yml +28 -0
- data/.travis.yml +27 -1
- data/Appraisals +27 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +9 -0
- data/Rakefile +9 -3
- data/gemfiles/activesupport_2.3_LTS.gemfile +16 -0
- data/gemfiles/activesupport_3.gemfile +16 -0
- data/gemfiles/activesupport_4.gemfile +15 -0
- data/gemfiles/activesupport_5.gemfile +15 -0
- data/gemfiles/activesupport_6.gemfile +15 -0
- data/gemfiles/activesupport_7.gemfile +15 -0
- data/lib/rrule/context.rb +5 -3
- data/lib/rrule/filters/by_month.rb +2 -0
- data/lib/rrule/filters/by_month_day.rb +2 -0
- data/lib/rrule/filters/by_week_day.rb +5 -3
- data/lib/rrule/filters/by_week_number.rb +2 -0
- data/lib/rrule/filters/by_year_day.rb +3 -1
- data/lib/rrule/frequencies/daily.rb +2 -0
- data/lib/rrule/frequencies/frequency.rb +4 -12
- data/lib/rrule/frequencies/monthly.rb +2 -0
- data/lib/rrule/frequencies/simple_weekly.rb +6 -6
- data/lib/rrule/frequencies/weekly.rb +2 -0
- data/lib/rrule/frequencies/yearly.rb +2 -0
- data/lib/rrule/generators/all_occurrences.rb +2 -0
- data/lib/rrule/generators/by_set_position.rb +2 -0
- data/lib/rrule/generators/generator.rb +5 -1
- data/lib/rrule/rule.rb +29 -37
- data/lib/rrule/version.rb +5 -0
- data/lib/rrule/weekday.rb +4 -2
- data/lib/rrule.rb +4 -0
- data/rrule.gemspec +18 -11
- data/scripts/benchmark.rb +3 -1
- metadata +30 -52
- data/spec/context_spec.rb +0 -261
- data/spec/filters/by_month_day_spec.rb +0 -35
- data/spec/filters/by_month_spec.rb +0 -35
- data/spec/filters/by_week_day_spec.rb +0 -35
- data/spec/filters/by_week_number_spec.rb +0 -41
- data/spec/filters/by_year_day_spec.rb +0 -35
- data/spec/frequencies/daily_spec.rb +0 -62
- data/spec/frequencies/monthly_spec.rb +0 -63
- data/spec/frequencies/simple_weekly_spec.rb +0 -32
- data/spec/frequencies/weekly_spec.rb +0 -92
- data/spec/frequencies/yearly_spec.rb +0 -54
- data/spec/generators/all_occurrences_spec.rb +0 -44
- data/spec/generators/by_set_position_spec.rb +0 -39
- data/spec/generators/generator_spec.rb +0 -110
- data/spec/rule_spec.rb +0 -2338
- data/spec/spec_helper.rb +0 -23
- data/spec/weekday_spec.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '007499934626da51ca670d58c30fab5efe4f88c782979eaff317f440e8f237fc'
|
4
|
+
data.tar.gz: a99135de58a44d1c71a2af4fee8721475f09c44cfd40ab21410c7cb755835784
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b2f9bc5d989d05bebf09aafac0ded5fd2148901481b15fce0b4ea60680cb26fefe4f6bfebe286473a02f25543e8be499b842020988da87226d6da3eaf847070f
|
7
|
+
data.tar.gz: 5b450cdde1f0b8c7a6c05a0520ecfdcb43e93647e2155a0fc2dc1578f7fdf4457c42a638fe31fadfd8bd31a1fc006169dab6847a03fa2552c530283c91f78870
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.6
|
3
|
+
Exclude:
|
4
|
+
- 'gemfiles/**/*'
|
5
|
+
- Appraisals
|
6
|
+
|
7
|
+
Layout:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Lint/NonLocalExitFromIterator:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Metrics:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Naming:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Style/Documentation:
|
20
|
+
Enabled: false
|
21
|
+
Style/MultilineBlockChain:
|
22
|
+
Enabled: false
|
23
|
+
Style/NumericPredicate:
|
24
|
+
Enabled: false
|
25
|
+
Style/RescueModifier:
|
26
|
+
Enabled: false
|
27
|
+
Style/TrailingCommaInArrayLiteral:
|
28
|
+
EnforcedStyleForMultiline: comma
|
data/.travis.yml
CHANGED
@@ -1,3 +1,29 @@
|
|
1
1
|
language: ruby
|
2
|
+
sudo: false
|
2
3
|
rvm:
|
3
|
-
- 2.
|
4
|
+
- 2.6.5
|
5
|
+
- 2.7.0
|
6
|
+
- 3.0.0
|
7
|
+
|
8
|
+
gemfile:
|
9
|
+
- gemfiles/activesupport_2.3_LTS.gemfile
|
10
|
+
- gemfiles/activesupport_3.gemfile
|
11
|
+
- gemfiles/activesupport_4.gemfile
|
12
|
+
- gemfiles/activesupport_5.gemfile
|
13
|
+
- gemfiles/activesupport_6.gemfile
|
14
|
+
- gemfiles/activesupport_7.gemfile
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
exclude:
|
18
|
+
- rvm: 2.7.0
|
19
|
+
gemfile: gemfiles/activesupport_3.gemfile
|
20
|
+
- rvm: 2.7.0
|
21
|
+
gemfile: gemfiles/activesupport_4.gemfile
|
22
|
+
- rvm: 3.0.0
|
23
|
+
gemfile: gemfiles/activesupport_3.gemfile
|
24
|
+
- rvm: 3.0.0
|
25
|
+
gemfile: gemfiles/activesupport_4.gemfile
|
26
|
+
|
27
|
+
before_install:
|
28
|
+
- yes | gem update --system --force
|
29
|
+
- gem install bundler
|
data/Appraisals
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
appraise 'activesupport-2.3-LTS' do
|
4
|
+
gem 'rexml'
|
5
|
+
gem 'activesupport', '>= 2', git: 'https://github.com/makandra/rails.git', branch: '2-3-lts'
|
6
|
+
end
|
7
|
+
|
8
|
+
appraise 'activesupport-3' do
|
9
|
+
gem 'activesupport', '~> 3'
|
10
|
+
gem 'tzinfo', '~> 1.2'
|
11
|
+
end
|
12
|
+
|
13
|
+
appraise 'activesupport-4' do
|
14
|
+
gem 'activesupport', '~> 4'
|
15
|
+
end
|
16
|
+
|
17
|
+
appraise 'activesupport-5' do
|
18
|
+
gem 'activesupport', '~> 5'
|
19
|
+
end
|
20
|
+
|
21
|
+
appraise 'activesupport-6' do
|
22
|
+
gem 'activesupport', '~> 6'
|
23
|
+
end
|
24
|
+
|
25
|
+
appraise 'activesupport-7' do
|
26
|
+
gem 'activesupport', '~> 7'
|
27
|
+
end
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
Change Log
|
2
2
|
==========
|
3
3
|
|
4
|
+
Version 0.4.4 *(2022-03-01)*
|
5
|
+
----------------------------
|
6
|
+
Remove constraint on ActiveSupport version
|
7
|
+
|
8
|
+
Version 0.4.3 *(2021-08-10)*
|
9
|
+
----------------------------
|
10
|
+
Adding support for multiple versions of ActiveSupport, up until at least ActiveSupport 6
|
11
|
+
Handle case where DTSTART is a date
|
12
|
+
Several bugfixes (fix weekday ordinal matching, BYDAY calculations with and without ordinals)
|
13
|
+
|
14
|
+
Version 0.4.2 *(2019-02-05)*
|
15
|
+
----------------------------
|
16
|
+
Truncate the floor_date option if it's less than the dtstart option
|
17
|
+
|
4
18
|
Version 0.4.1 *(2018-11-28)*
|
5
19
|
----------------------------
|
6
20
|
Fix bug in SimpleWeekly when ENV['TZ'] was not equal to time zone of rrule
|
data/Gemfile
CHANGED
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('
|
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 :
|
15
|
+
task all: ['spec']
|
10
16
|
end
|
11
17
|
|
12
|
-
task :
|
18
|
+
task default: %w[spec:all rubocop]
|
@@ -0,0 +1,16 @@
|
|
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: "../"
|
@@ -0,0 +1,16 @@
|
|
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: "../"
|
@@ -0,0 +1,15 @@
|
|
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: "../"
|
@@ -0,0 +1,15 @@
|
|
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", "~> 5"
|
10
|
+
|
11
|
+
platforms :mri do
|
12
|
+
gem "pry-byebug"
|
13
|
+
end
|
14
|
+
|
15
|
+
gemspec path: "../"
|
@@ -0,0 +1,15 @@
|
|
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", "~> 6"
|
10
|
+
|
11
|
+
platforms :mri do
|
12
|
+
gem "pry-byebug"
|
13
|
+
end
|
14
|
+
|
15
|
+
gemspec path: "../"
|
@@ -0,0 +1,15 @@
|
|
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", "~> 7"
|
10
|
+
|
11
|
+
platforms :mri do
|
12
|
+
gem "pry-byebug"
|
13
|
+
end
|
14
|
+
|
15
|
+
gemspec path: "../"
|
data/lib/rrule/context.rb
CHANGED
@@ -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 |
|
21
|
-
possible_date_ranges.push(elapsed_days_in_year_by_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)..
|
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 ByWeekDay
|
3
5
|
def initialize(weekdays, context)
|
@@ -6,17 +8,17 @@ module RRule
|
|
6
8
|
end
|
7
9
|
|
8
10
|
def reject?(i)
|
9
|
-
masked?(i)
|
11
|
+
masked?(i) && !matches_by_week_days?(i)
|
10
12
|
end
|
11
13
|
|
12
14
|
private
|
13
15
|
|
14
16
|
def masked?(i)
|
15
|
-
context.day_of_year_mask
|
17
|
+
context.day_of_year_mask.blank? || !context.day_of_year_mask[i]
|
16
18
|
end
|
17
19
|
|
18
20
|
def matches_by_week_days?(i)
|
19
|
-
by_week_days.
|
21
|
+
by_week_days.present? && by_week_days.include?(context.weekday_by_day_of_year[i])
|
20
22
|
end
|
21
23
|
|
22
24
|
attr_reader :by_week_days, :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 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,
|
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 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
|
-
|
13
|
+
target_wday = if context.options[:byweekday].present?
|
14
|
+
context.options[:byweekday].first.index
|
13
15
|
else
|
14
|
-
|
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 Generator
|
3
5
|
attr_reader :context
|
@@ -7,6 +9,8 @@ module RRule
|
|
7
9
|
end
|
8
10
|
|
9
11
|
def process_timeset(date, timeset)
|
12
|
+
return [date] if timeset.blank?
|
13
|
+
|
10
14
|
timeset.map do |time|
|
11
15
|
hour_sets = (
|
12
16
|
Array.wrap(time[:hour]).sort.map do |hour|
|
@@ -31,4 +35,4 @@ module RRule
|
|
31
35
|
end.flatten
|
32
36
|
end
|
33
37
|
end
|
34
|
-
end
|
38
|
+
end
|
data/lib/rrule/rule.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RRule
|
2
4
|
class Rule
|
3
5
|
include Enumerable
|
@@ -6,7 +8,7 @@ module RRule
|
|
6
8
|
|
7
9
|
def initialize(rrule, dtstart: Time.now, tzid: 'UTC', exdate: [], max_year: nil)
|
8
10
|
@tz = tzid
|
9
|
-
@dtstart = floor_to_seconds_in_timezone(dtstart)
|
11
|
+
@dtstart = dtstart.is_a?(Date) ? dtstart : floor_to_seconds_in_timezone(dtstart)
|
10
12
|
@exdate = exdate
|
11
13
|
@options = parse_options(rrule)
|
12
14
|
@frequency_type = Frequency.for_options(options)
|
@@ -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
|
-
|
51
|
+
generator = if options[:bysetpos]
|
52
|
+
BySetPosition.new(options[:bysetpos], context)
|
64
53
|
else
|
65
|
-
|
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)
|
@@ -106,7 +95,8 @@ module RRule
|
|
106
95
|
def parse_options(rule)
|
107
96
|
options = { interval: 1, wkst: 1 }
|
108
97
|
|
109
|
-
|
98
|
+
# Remove RRULE: prefix to prevent parsing options incorrectly.
|
99
|
+
params = rule.delete_prefix('RRULE:').split(';')
|
110
100
|
params.each do |param|
|
111
101
|
option, value = param.split('=')
|
112
102
|
|
@@ -117,15 +107,17 @@ module RRule
|
|
117
107
|
i = begin
|
118
108
|
Integer(value)
|
119
109
|
rescue ArgumentError
|
120
|
-
raise InvalidRRule,
|
110
|
+
raise InvalidRRule, 'COUNT must be a non-negative integer'
|
121
111
|
end
|
122
|
-
raise InvalidRRule,
|
112
|
+
raise InvalidRRule, 'COUNT must be a non-negative integer' if i < 0
|
123
113
|
options[:count] = i
|
124
114
|
when 'UNTIL'
|
125
|
-
|
115
|
+
# The value of the UNTIL rule part MUST have the same
|
116
|
+
# value type as the "DTSTART" property.
|
117
|
+
options[:until] = @dtstart.is_a?(Date) ? Date.parse(value) : Time.parse(value)
|
126
118
|
when 'INTERVAL'
|
127
119
|
i = Integer(value) rescue 0
|
128
|
-
raise InvalidRRule,
|
120
|
+
raise InvalidRRule, 'INTERVAL must be a positive integer' unless i > 0
|
129
121
|
options[:interval] = i
|
130
122
|
when 'BYHOUR'
|
131
123
|
options[:byhour] = value.split(',').compact.map(&:to_i)
|
@@ -138,7 +130,7 @@ module RRule
|
|
138
130
|
when 'BYSETPOS'
|
139
131
|
options[:bysetpos] = value.split(',').map(&:to_i)
|
140
132
|
when 'WKST'
|
141
|
-
options[:wkst] =
|
133
|
+
options[:wkst] = RRule::WEEKDAYS.index(value)
|
142
134
|
when 'BYMONTH'
|
143
135
|
options[:bymonth] = value.split(',').compact.map(&:to_i)
|
144
136
|
when 'BYMONTHDAY'
|
@@ -150,12 +142,10 @@ module RRule
|
|
150
142
|
end
|
151
143
|
end
|
152
144
|
|
153
|
-
|
145
|
+
unless options[:byweekno] || options[:byyearday] || options[:bymonthday] || options[:byweekday]
|
154
146
|
case options[:freq]
|
155
147
|
when 'YEARLY'
|
156
|
-
unless options[:bymonth]
|
157
|
-
options[:bymonth] = [dtstart.month]
|
158
|
-
end
|
148
|
+
options[:bymonth] = [dtstart.month] unless options[:bymonth]
|
159
149
|
options[:bymonthday] = [dtstart.day]
|
160
150
|
when 'MONTHLY'
|
161
151
|
options[:bymonthday] = [dtstart.day]
|
@@ -165,11 +155,13 @@ module RRule
|
|
165
155
|
end
|
166
156
|
end
|
167
157
|
|
168
|
-
unless options[:byweekday].nil?
|
169
|
-
options[:byweekday], options[:bynweekday] = options[:byweekday].partition { |wday| wday.ordinal.nil? }
|
170
|
-
end
|
158
|
+
options[:byweekday], options[:bynweekday] = options[:byweekday].partition { |wday| wday.ordinal.nil? } unless options[:byweekday].nil?
|
171
159
|
|
172
|
-
|
160
|
+
# The BYSECOND, BYMINUTE and BYHOUR rule parts MUST NOT be specified
|
161
|
+
# when the associated "DTSTART" property has a DATE value type.
|
162
|
+
# These rule parts MUST be ignored in RECUR value that violate the
|
163
|
+
# above requirement
|
164
|
+
options[:timeset] = [{ hour: (options[:byhour].presence || dtstart.hour), minute: (options[:byminute].presence || dtstart.min), second: (options[:bysecond].presence || dtstart.sec) }] unless dtstart.is_a?(Date)
|
173
165
|
|
174
166
|
options
|
175
167
|
end
|
data/lib/rrule/weekday.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RRule
|
2
4
|
class Weekday
|
3
5
|
attr_reader :index, :ordinal
|
@@ -8,8 +10,8 @@ module RRule
|
|
8
10
|
end
|
9
11
|
|
10
12
|
def self.parse(weekday)
|
11
|
-
match = /([+-]?\d)?([A-Z]{2})/.match(weekday)
|
12
|
-
index =
|
13
|
+
match = /([+-]?\d+)?([A-Z]{2})/.match(weekday)
|
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
|