ice_cube 0.4.5 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|