ice_cube 0.4.5 → 0.5.0
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.
- data/lib/ice_cube/rule.rb +5 -5
- data/lib/ice_cube/rule_occurrence.rb +4 -3
- data/lib/ice_cube/rules/daily_rule.rb +1 -1
- data/lib/ice_cube/rules/hourly_rule.rb +1 -1
- data/lib/ice_cube/rules/minutely_rule.rb +1 -1
- data/lib/ice_cube/rules/monthly_rule.rb +4 -8
- data/lib/ice_cube/rules/secondly_rule.rb +1 -1
- data/lib/ice_cube/rules/weekly_rule.rb +1 -1
- data/lib/ice_cube/rules/yearly_rule.rb +3 -7
- data/lib/ice_cube/schedule.rb +3 -3
- data/lib/ice_cube/time_util.rb +44 -4
- data/lib/ice_cube/version.rb +1 -1
- metadata +11 -4
data/lib/ice_cube/rule.rb
CHANGED
@@ -90,7 +90,7 @@ module IceCube
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
-
# The key - extremely educated guesses
|
93
|
+
# The key to speed - extremely educated guesses
|
94
94
|
# This spidering behavior will go through look for the next suggestion
|
95
95
|
# by constantly moving the farthest back value forward
|
96
96
|
def next_suggestion(date)
|
@@ -100,13 +100,13 @@ module IceCube
|
|
100
100
|
compact_suggestions = suggestions.values.compact
|
101
101
|
# find the next date to go to
|
102
102
|
if compact_suggestions.empty?
|
103
|
-
|
103
|
+
attempt_count = 0
|
104
104
|
loop do
|
105
105
|
# keep going through rule suggestions
|
106
|
-
next_date = self.default_jump(
|
107
|
-
return next_date if validate_single_date(next_date)
|
106
|
+
next_date = self.default_jump(date, attempt_count += 1)
|
107
|
+
return next_date if !next_date.nil? && validate_single_date(next_date)
|
108
108
|
end
|
109
|
-
else
|
109
|
+
else
|
110
110
|
loop do
|
111
111
|
compact_suggestions = suggestions.values.compact
|
112
112
|
min_suggestion = compact_suggestions.min
|
@@ -41,12 +41,13 @@ module IceCube
|
|
41
41
|
else
|
42
42
|
date = @rule.next_suggestion(@date)
|
43
43
|
end
|
44
|
-
#walk through all of the successive dates, looking for the next occurrence (interval-valid), then return it.
|
44
|
+
# walk through all of the successive dates, looking for the next occurrence (interval-valid), then return it.
|
45
45
|
begin
|
46
|
-
return nil if yield(date)
|
47
46
|
return nil if @end_time && date > @end_time
|
48
47
|
return nil if @rule.until_date && date > @rule.until_date # until check
|
49
|
-
|
48
|
+
next unless @rule.in_interval?(date, @start_date)
|
49
|
+
return nil if yield(date)
|
50
|
+
return RuleOccurrence.new(@rule, @start_date, @end_time, date, @index + 1)
|
50
51
|
end while date = @rule.next_suggestion(date)
|
51
52
|
end
|
52
53
|
|
@@ -7,8 +7,8 @@ module IceCube
|
|
7
7
|
# and either (1) we're on a valid day of the week (ie: first sunday of the month)
|
8
8
|
# or we're on a valid day of the month (1, 15, -1)
|
9
9
|
# Note: Rollover is not implemented, so the 35th day of the month is invalid.
|
10
|
-
def in_interval?(date, start_date)
|
11
|
-
#make sure we're in the proper interval
|
10
|
+
def in_interval?(date, start_date)
|
11
|
+
# make sure we're in the proper interval
|
12
12
|
months_to_start_date = (date.month - start_date.month) + (date.year - start_date.year) * 12
|
13
13
|
months_to_start_date % @interval == 0
|
14
14
|
end
|
@@ -23,12 +23,8 @@ module IceCube
|
|
23
23
|
|
24
24
|
protected
|
25
25
|
|
26
|
-
def default_jump(date)
|
27
|
-
|
28
|
-
@interval.times do
|
29
|
-
goal += TimeUtil.days_in_month(goal) * ONE_DAY
|
30
|
-
end
|
31
|
-
adjust(goal, date)
|
26
|
+
def default_jump(date, attempt_count = 1)
|
27
|
+
TimeUtil.date_in_n_months(date, attempt_count * @interval)
|
32
28
|
end
|
33
29
|
|
34
30
|
private
|
@@ -24,13 +24,9 @@ module IceCube
|
|
24
24
|
protected
|
25
25
|
|
26
26
|
# one year from now, the same month and day of the year
|
27
|
-
def default_jump(date)
|
28
|
-
#jump by months since there's no reliable way to jump by year
|
29
|
-
|
30
|
-
(@interval * 12).times do
|
31
|
-
goal += TimeUtil.days_in_month(goal) * ONE_DAY
|
32
|
-
end
|
33
|
-
adjust(goal, date)
|
27
|
+
def default_jump(date, attempt_count = 1)
|
28
|
+
# jump by months since there's no reliable way to jump by year
|
29
|
+
TimeUtil.date_in_n_months(date, attempt_count * @interval * 12)
|
34
30
|
end
|
35
31
|
|
36
32
|
private
|
data/lib/ice_cube/schedule.rb
CHANGED
@@ -125,9 +125,9 @@ module IceCube
|
|
125
125
|
|
126
126
|
# Retrieve the first (n) occurrences of the schedule. May return less than
|
127
127
|
# n results, if the rules end before n results are reached.
|
128
|
-
def first(n =
|
129
|
-
dates = find_occurrences { |head| head.first(n) }
|
130
|
-
dates.slice(0, n)
|
128
|
+
def first(n = nil)
|
129
|
+
dates = find_occurrences { |head| head.first(n || 1) }
|
130
|
+
n.nil? ? dates.first : dates.slice(0, n)
|
131
131
|
end
|
132
132
|
|
133
133
|
# Add a rule of any type as an recurrence in this schedule
|
data/lib/ice_cube/time_util.rb
CHANGED
@@ -16,16 +16,56 @@ module TimeUtil
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
# TODO can we improve this more?
|
20
|
+
def self.date_in_n_months(date, month_distance)
|
21
|
+
|
22
|
+
next_mark = date
|
23
|
+
days_in_month_of_next_mark = days_in_month(next_mark)
|
24
|
+
|
25
|
+
month_distance.times do
|
26
|
+
|
27
|
+
prev_mark = next_mark
|
28
|
+
next_mark += days_in_month_of_next_mark * ONE_DAY
|
29
|
+
|
30
|
+
# only moving one day at a time, so this suffices
|
31
|
+
months_covered = next_mark.month - prev_mark.month
|
32
|
+
months_covered += 12 if months_covered < 0
|
33
|
+
|
34
|
+
# step back to the end of the previous month of months_covered went too far
|
35
|
+
if months_covered == 2
|
36
|
+
next_mark -= next_mark.mday * ONE_DAY
|
37
|
+
end
|
38
|
+
|
39
|
+
days_in_month_of_next_mark = days_in_month(next_mark)
|
40
|
+
next_mark = adjust(next_mark, prev_mark)
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
# at the end, there's a chance we're not on the correct day,
|
45
|
+
# but if we're not - we will always be behind it in the correct month
|
46
|
+
# if there exists no proper day in the month for us, return nil - otherwise, return that date
|
47
|
+
|
48
|
+
if days_in_month_of_next_mark >= date.mday
|
49
|
+
next_mark += (date.mday - next_mark.mday) * ONE_DAY
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def adjust(goal, date)
|
55
|
+
return goal if goal.utc_offset == date.utc_offset
|
56
|
+
goal - goal.utc_offset + date.utc_offset
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.is_leap?(year)
|
60
|
+
(year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
|
21
61
|
end
|
22
62
|
|
23
63
|
def self.days_in_year(date)
|
24
|
-
is_leap?(date) ? 366 : 365
|
64
|
+
is_leap?(date.year) ? 366 : 365
|
25
65
|
end
|
26
66
|
|
27
67
|
def self.days_in_month(date)
|
28
|
-
is_leap?(date) ? LeapYearMonthDays[date.month - 1] : CommonYearMonthDays[date.month - 1]
|
68
|
+
is_leap?(date.year) ? LeapYearMonthDays[date.month - 1] : CommonYearMonthDays[date.month - 1]
|
29
69
|
end
|
30
70
|
|
31
71
|
def self.ical_format(time)
|
data/lib/ice_cube/version.rb
CHANGED
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ice_cube
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 11
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
- 4
|
8
8
|
- 5
|
9
|
-
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- John Crepezzi
|
@@ -14,16 +15,18 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-08-
|
18
|
+
date: 2010-08-04 00:00:00 -04:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: rspec
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ">="
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
27
30
|
segments:
|
28
31
|
- 0
|
29
32
|
version: "0"
|
@@ -71,23 +74,27 @@ rdoc_options: []
|
|
71
74
|
require_paths:
|
72
75
|
- lib
|
73
76
|
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
74
78
|
requirements:
|
75
79
|
- - ">="
|
76
80
|
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
77
82
|
segments:
|
78
83
|
- 0
|
79
84
|
version: "0"
|
80
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
81
87
|
requirements:
|
82
88
|
- - ">="
|
83
89
|
- !ruby/object:Gem::Version
|
90
|
+
hash: 3
|
84
91
|
segments:
|
85
92
|
- 0
|
86
93
|
version: "0"
|
87
94
|
requirements: []
|
88
95
|
|
89
96
|
rubyforge_project: ice-cube
|
90
|
-
rubygems_version: 1.3.
|
97
|
+
rubygems_version: 1.3.7
|
91
98
|
signing_key:
|
92
99
|
specification_version: 3
|
93
100
|
summary: Ruby Date Recurrence Library
|