ice_cube 0.11.0 → 0.11.1
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 +7 -0
- data/lib/ice_cube.rb +0 -11
- data/lib/ice_cube/builders/string_builder.rb +15 -23
- data/lib/ice_cube/deprecated.rb +26 -24
- data/lib/ice_cube/enumerator.rb +1 -3
- data/lib/ice_cube/hash_input.rb +71 -0
- data/lib/ice_cube/rule.rb +4 -6
- 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 +1 -1
- data/lib/ice_cube/rules/secondly_rule.rb +1 -1
- data/lib/ice_cube/rules/yearly_rule.rb +1 -1
- data/lib/ice_cube/schedule.rb +4 -4
- data/lib/ice_cube/string_helpers.rb +10 -0
- data/lib/ice_cube/time_util.rb +14 -5
- data/lib/ice_cube/validations/count.rb +4 -6
- data/lib/ice_cube/validations/daily_interval.rb +13 -18
- data/lib/ice_cube/validations/day.rb +4 -4
- data/lib/ice_cube/validations/day_of_month.rb +8 -10
- data/lib/ice_cube/validations/day_of_week.rb +24 -26
- data/lib/ice_cube/validations/day_of_year.rb +11 -12
- data/lib/ice_cube/validations/hour_of_day.rb +9 -11
- data/lib/ice_cube/validations/hourly_interval.rb +18 -21
- data/lib/ice_cube/validations/lock.rb +35 -14
- data/lib/ice_cube/validations/minute_of_hour.rb +9 -11
- data/lib/ice_cube/validations/minutely_interval.rb +16 -19
- data/lib/ice_cube/validations/month_of_year.rb +4 -4
- data/lib/ice_cube/validations/monthly_interval.rb +15 -17
- data/lib/ice_cube/validations/schedule_lock.rb +12 -11
- data/lib/ice_cube/validations/second_of_minute.rb +5 -5
- data/lib/ice_cube/validations/secondly_interval.rb +13 -16
- data/lib/ice_cube/validations/until.rb +12 -12
- data/lib/ice_cube/validations/weekly_interval.rb +20 -23
- data/lib/ice_cube/validations/yearly_interval.rb +10 -11
- data/lib/ice_cube/version.rb +1 -1
- metadata +20 -33
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0cf51eea4a5e3f9a8c15eedc224978494d2a79df
|
4
|
+
data.tar.gz: 8daed67d6ab9f6e610ea40c08e7e032a96552e47
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7acfe2a1546d074b0b43a9250ce4e937f339f084fd3abf9a04b840cc529849140d224b4d2bdd134254ecf1088c19e6845fce195b9440eea2fddbb31baa25ca2b
|
7
|
+
data.tar.gz: d722e7ef0d0ee4fb2bfaaf5e28b330df6898ad49f183f2cb0ab43e6115bcf91be64cd07755df568318dd83deffe94439b83ec8ba0c60f2b06711d39a3c174534
|
data/lib/ice_cube.rb
CHANGED
@@ -1,13 +1,6 @@
|
|
1
1
|
require 'date'
|
2
2
|
require 'ice_cube/deprecated'
|
3
3
|
|
4
|
-
# Use psych if we can
|
5
|
-
begin
|
6
|
-
require 'psych'
|
7
|
-
rescue LoadError
|
8
|
-
require 'yaml'
|
9
|
-
end
|
10
|
-
|
11
4
|
module IceCube
|
12
5
|
|
13
6
|
autoload :VERSION, 'ice_cube/version'
|
@@ -71,10 +64,6 @@ module IceCube
|
|
71
64
|
ONE_DAY = ONE_HOUR * 24
|
72
65
|
ONE_WEEK = ONE_DAY * 7
|
73
66
|
|
74
|
-
def self.use_psych?
|
75
|
-
@use_psych ||= defined?(Psych) && defined?(Psych::VERSION)
|
76
|
-
end
|
77
|
-
|
78
67
|
# Defines the format used by IceCube when printing out Schedule#to_s.
|
79
68
|
# Defaults to '%B %e, %Y'
|
80
69
|
def self.to_s_time_format
|
@@ -13,32 +13,26 @@ module IceCube
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def to_s
|
16
|
-
|
17
|
-
res = @types.map do |type, segments|
|
16
|
+
@types.each_with_object(@base || '') do |(type, segments), str|
|
18
17
|
if f = self.class.formatter(type)
|
19
|
-
str << ' '
|
18
|
+
str << ' ' << f.call(segments)
|
20
19
|
else
|
21
20
|
next if segments.empty?
|
22
|
-
str << ' '
|
21
|
+
str << ' ' << self.class.sentence(segments)
|
23
22
|
end
|
24
23
|
end
|
25
|
-
str
|
26
24
|
end
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
@formatters[type]
|
32
|
-
end
|
33
|
-
|
34
|
-
def register_formatter(type, &formatter)
|
35
|
-
@formatters ||= {}
|
36
|
-
@formatters[type] = formatter
|
37
|
-
end
|
26
|
+
def self.formatter(type)
|
27
|
+
@formatters[type]
|
28
|
+
end
|
38
29
|
|
30
|
+
def self.register_formatter(type, &formatter)
|
31
|
+
@formatters ||= {}
|
32
|
+
@formatters[type] = formatter
|
39
33
|
end
|
40
34
|
|
41
|
-
|
35
|
+
module Helpers
|
42
36
|
|
43
37
|
NUMBER_SUFFIX = ['th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th']
|
44
38
|
SPECIAL_SUFFIX = { 11 => 'th', 12 => 'th', 13 => 'th', 14 => 'th' }
|
@@ -54,21 +48,19 @@ module IceCube
|
|
54
48
|
end
|
55
49
|
|
56
50
|
def nice_number(number)
|
57
|
-
if number == -1
|
58
|
-
|
59
|
-
|
60
|
-
suffix = SPECIAL_SUFFIX.include?(number) ?
|
61
|
-
SPECIAL_SUFFIX[number] : NUMBER_SUFFIX[number.abs % 10]
|
51
|
+
return 'last' if number == -1
|
52
|
+
suffix = SPECIAL_SUFFIX[number] || NUMBER_SUFFIX[number.abs % 10]
|
53
|
+
if number < -1
|
62
54
|
number.abs.to_s << suffix << ' to last'
|
63
55
|
else
|
64
|
-
suffix = SPECIAL_SUFFIX.include?(number) ?
|
65
|
-
SPECIAL_SUFFIX[number] : NUMBER_SUFFIX[number.abs % 10]
|
66
56
|
number.to_s << suffix
|
67
57
|
end
|
68
58
|
end
|
69
59
|
|
70
60
|
end
|
71
61
|
|
62
|
+
extend Helpers
|
63
|
+
|
72
64
|
end
|
73
65
|
|
74
66
|
end
|
data/lib/ice_cube/deprecated.rb
CHANGED
@@ -1,28 +1,30 @@
|
|
1
|
-
module
|
1
|
+
module IceCube
|
2
|
+
module Deprecated
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
# Define a deprecated alias for a method
|
5
|
+
# @param [Symbol] name - name of method to define
|
6
|
+
# @param [Symbol] replacement - name of method to replace (alias)
|
7
|
+
def deprecated_alias(name, replacement)
|
8
|
+
# Create a wrapped version
|
9
|
+
define_method(name) do |*args, &block|
|
10
|
+
warn "IceCube: ##{name} deprecated (please use ##{replacement})"
|
11
|
+
send replacement, *args, &block
|
12
|
+
end
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
15
|
+
# Deprecate a defined method
|
16
|
+
# @param [Symbol] name - name of deprecated method
|
17
|
+
# @param [Symbol] replacement - name of the desired replacement
|
18
|
+
def deprecated(name, replacement)
|
19
|
+
# Replace old method
|
20
|
+
old_name = :"#{name}_without_deprecation"
|
21
|
+
alias_method old_name, name
|
22
|
+
# And replace it with a wrapped version
|
23
|
+
define_method(name) do |*args, &block|
|
24
|
+
warn "IceCube: ##{name} deprecated (please use ##{replacement})"
|
25
|
+
send old_name, *args, &block
|
26
|
+
end
|
27
|
+
end
|
27
28
|
|
29
|
+
end
|
28
30
|
end
|
data/lib/ice_cube/enumerator.rb
CHANGED
@@ -19,11 +19,9 @@ module IceCube
|
|
19
19
|
def find_next
|
20
20
|
loop do
|
21
21
|
min_time = recurrence_rules.reduce(nil) do |min_time, rule|
|
22
|
-
|
22
|
+
catch :limit do
|
23
23
|
new_time = rule.next_time(time, schedule, min_time || @to_time)
|
24
24
|
[min_time, new_time].compact.min
|
25
|
-
rescue CountExceeded, UntilExceeded
|
26
|
-
min_time
|
27
25
|
end
|
28
26
|
end
|
29
27
|
break nil unless min_time
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module IceCube
|
2
|
+
class HashInput
|
3
|
+
|
4
|
+
class Mash
|
5
|
+
def initialize(hash)
|
6
|
+
@hash = hash
|
7
|
+
end
|
8
|
+
|
9
|
+
# Fetch values indifferently by symbol or string key without symbolizing
|
10
|
+
# arbitrary string input
|
11
|
+
#
|
12
|
+
def [](key)
|
13
|
+
@hash.fetch(key) do |key|
|
14
|
+
str_key = key.to_s
|
15
|
+
@hash.each_pair.detect do |sym_key, value|
|
16
|
+
return value if sym_key.to_s == str_key
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(hash)
|
23
|
+
@input = Mash.new(hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](key)
|
27
|
+
@input[key]
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_rule
|
31
|
+
return nil unless rule_class
|
32
|
+
rule = rule_class.new(interval, week_start)
|
33
|
+
rule.until(limit_time) if limit_time
|
34
|
+
rule.count(limit_count) if limit_count
|
35
|
+
validations.each do |validation, args|
|
36
|
+
rule.send(validation, *args)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def rule_class
|
41
|
+
return @rule_class if @rule_class
|
42
|
+
match = @input[:rule_type].match(/::(\w+Rule)$/)
|
43
|
+
@rule_class = IceCube.const_get(match[1]) if match
|
44
|
+
end
|
45
|
+
|
46
|
+
def interval
|
47
|
+
@input[:interval] || 1
|
48
|
+
end
|
49
|
+
|
50
|
+
def week_start
|
51
|
+
@input[:week_start] || :sunday
|
52
|
+
end
|
53
|
+
|
54
|
+
def limit_time
|
55
|
+
@limit_time ||= TimeUtil.deserialize_time(@input[:until])
|
56
|
+
end
|
57
|
+
|
58
|
+
def limit_count
|
59
|
+
@input[:count]
|
60
|
+
end
|
61
|
+
|
62
|
+
def validations
|
63
|
+
input_validations = Mash.new(@input[:validations] || {})
|
64
|
+
ValidatedRule::VALIDATION_ORDER.each_with_object({}) do |key, output_validations|
|
65
|
+
args = input_validations[key]
|
66
|
+
output_validations[key] = Array(args) if args
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
data/lib/ice_cube/rule.rb
CHANGED
@@ -23,24 +23,22 @@ module IceCube
|
|
23
23
|
h.nil? ? super : h.hash
|
24
24
|
end
|
25
25
|
|
26
|
-
# Expected to be overridden by subclasses
|
27
26
|
def to_ical
|
28
|
-
|
27
|
+
raise MethodNotImplemented, "Expected to be overrridden by subclasses"
|
29
28
|
end
|
30
29
|
|
31
30
|
# Yaml implementation
|
32
31
|
def to_yaml(*args)
|
33
|
-
|
32
|
+
YAML::dump(to_hash, *args)
|
34
33
|
end
|
35
34
|
|
36
35
|
# From yaml
|
37
36
|
def self.from_yaml(yaml)
|
38
|
-
from_hash
|
37
|
+
from_hash YAML::load(yaml)
|
39
38
|
end
|
40
39
|
|
41
|
-
# Expected to be overridden by subclasses
|
42
40
|
def to_hash
|
43
|
-
|
41
|
+
raise MethodNotImplemented, "Expected to be overridden by subclasses"
|
44
42
|
end
|
45
43
|
|
46
44
|
# Convert from a hash and create a rule
|
data/lib/ice_cube/schedule.rb
CHANGED
@@ -4,7 +4,7 @@ module IceCube
|
|
4
4
|
|
5
5
|
class Schedule
|
6
6
|
|
7
|
-
extend
|
7
|
+
extend Deprecated
|
8
8
|
|
9
9
|
# Get the start time
|
10
10
|
attr_reader :start_time
|
@@ -237,7 +237,7 @@ module IceCube
|
|
237
237
|
def conflicts_with?(other_schedule, closing_time = nil)
|
238
238
|
closing_time = TimeUtil.ensure_time closing_time
|
239
239
|
unless terminating? || other_schedule.terminating? || closing_time
|
240
|
-
raise ArgumentError
|
240
|
+
raise ArgumentError, "One or both schedules must be terminating to use #conflicts_with?"
|
241
241
|
end
|
242
242
|
# Pick the terminating schedule, and other schedule
|
243
243
|
# No need to reverse if terminating? or there is a closing time
|
@@ -313,12 +313,12 @@ module IceCube
|
|
313
313
|
|
314
314
|
# Convert the schedule to yaml
|
315
315
|
def to_yaml(*args)
|
316
|
-
|
316
|
+
YAML::dump(to_hash, *args)
|
317
317
|
end
|
318
318
|
|
319
319
|
# Load the schedule from yaml
|
320
320
|
def self.from_yaml(yaml, options = {})
|
321
|
-
hash =
|
321
|
+
hash = YAML::load(yaml)
|
322
322
|
if match = yaml.match(/start_date: .+((?:-|\+)\d{2}:\d{2})$/)
|
323
323
|
TimeUtil.restore_deserialized_offset(hash[:start_date], match[1])
|
324
324
|
end
|
data/lib/ice_cube/time_util.rb
CHANGED
@@ -3,7 +3,7 @@ require 'date'
|
|
3
3
|
module IceCube
|
4
4
|
module TimeUtil
|
5
5
|
|
6
|
-
extend
|
6
|
+
extend Deprecated
|
7
7
|
|
8
8
|
DAYS = {
|
9
9
|
:sunday => 0, :monday => 1, :tuesday => 2, :wednesday => 3,
|
@@ -82,7 +82,7 @@ module IceCube
|
|
82
82
|
# keep it. If it was serialized with a different offset than local TZ it
|
83
83
|
# will lose the zone and not support DST.
|
84
84
|
def self.restore_deserialized_offset(time, orig_offset_str)
|
85
|
-
return time if time.respond_to?(:time_zone)
|
85
|
+
return time if time.respond_to?(:time_zone) ||
|
86
86
|
time.getlocal(orig_offset_str).utc_offset == time.utc_offset
|
87
87
|
warn 'IceCube: parsed Time from nonlocal TZ. Use ActiveSupport to fix DST'
|
88
88
|
time.localtime(orig_offset_str)
|
@@ -113,21 +113,30 @@ module IceCube
|
|
113
113
|
# Convert a symbol to a numeric month
|
114
114
|
def self.sym_to_month(sym)
|
115
115
|
return wday = sym if (1..12).include? sym
|
116
|
-
MONTHS.fetch(sym)
|
116
|
+
MONTHS.fetch(sym) do |k|
|
117
|
+
raise ArgumentError, "Expecting Fixnum or Symbol value for month. " \
|
118
|
+
"No such month: #{k.inspect}"
|
119
|
+
end
|
117
120
|
end
|
118
121
|
deprecated_alias :symbol_to_month, :sym_to_month
|
119
122
|
|
120
123
|
# Convert a symbol to a wday number
|
121
124
|
def self.sym_to_wday(sym)
|
122
125
|
return sym if (0..6).include? sym
|
123
|
-
DAYS.fetch(sym)
|
126
|
+
DAYS.fetch(sym) do |k|
|
127
|
+
raise ArgumentError, "Expecting Fixnum or Symbol value for weekday. " \
|
128
|
+
"No such weekday: #{k.inspect}"
|
129
|
+
end
|
124
130
|
end
|
125
131
|
deprecated_alias :symbol_to_day, :sym_to_wday
|
126
132
|
|
127
133
|
# Convert wday number to day symbol
|
128
134
|
def self.wday_to_sym(wday)
|
129
135
|
return sym = wday if DAYS.keys.include? wday
|
130
|
-
DAYS.invert.fetch(wday)
|
136
|
+
DAYS.invert.fetch(wday) do |i|
|
137
|
+
raise ArgumentError, "Expecting Fixnum value for weekday. " \
|
138
|
+
"No such wday number: #{i.inspect}"
|
139
|
+
end
|
131
140
|
end
|
132
141
|
|
133
142
|
# Convert weekday from base sunday to the schedule's week start.
|
@@ -2,7 +2,7 @@ module IceCube
|
|
2
2
|
|
3
3
|
module Validations::Count
|
4
4
|
|
5
|
-
#
|
5
|
+
# Value reader for limit
|
6
6
|
def occurrence_count
|
7
7
|
@count
|
8
8
|
end
|
@@ -12,7 +12,7 @@ module IceCube
|
|
12
12
|
raise ArgumentError, "Expecting Fixnum or nil value for count, got #{max.inspect}"
|
13
13
|
end
|
14
14
|
@count = max
|
15
|
-
replace_validations_for(:count, [Validation.new(max, self)])
|
15
|
+
replace_validations_for(:count, max && [Validation.new(max, self)])
|
16
16
|
self
|
17
17
|
end
|
18
18
|
|
@@ -26,13 +26,11 @@ module IceCube
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def type
|
29
|
-
:
|
29
|
+
:limit
|
30
30
|
end
|
31
31
|
|
32
32
|
def validate(time, schedule)
|
33
|
-
if rule.uses && rule.uses >= count
|
34
|
-
raise CountExceeded
|
35
|
-
end
|
33
|
+
raise CountExceeded if rule.uses && rule.uses >= count
|
36
34
|
end
|
37
35
|
|
38
36
|
def build_s(builder)
|