ice_cube 0.16.0 → 0.16.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.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/config/locales/de.yml +1 -1
  3. data/config/locales/en.yml +7 -46
  4. data/config/locales/es.yml +47 -83
  5. data/config/locales/fr.yml +2 -2
  6. data/config/locales/it.yml +179 -0
  7. data/config/locales/ja.yml +52 -29
  8. data/config/locales/nl.yml +133 -0
  9. data/config/locales/pt-BR.yml +178 -0
  10. data/config/locales/sv.yml +1 -1
  11. data/lib/ice_cube/i18n.rb +11 -12
  12. data/lib/ice_cube/input_alignment.rb +89 -0
  13. data/lib/ice_cube/null_i18n.rb +12 -6
  14. data/lib/ice_cube/occurrence.rb +25 -23
  15. data/lib/ice_cube/parsers/ical_parser.rb +8 -5
  16. data/lib/ice_cube/rule.rb +5 -13
  17. data/lib/ice_cube/rules/daily_rule.rb +9 -0
  18. data/lib/ice_cube/rules/hourly_rule.rb +9 -0
  19. data/lib/ice_cube/rules/minutely_rule.rb +9 -0
  20. data/lib/ice_cube/rules/monthly_rule.rb +9 -0
  21. data/lib/ice_cube/rules/secondly_rule.rb +9 -0
  22. data/lib/ice_cube/rules/weekly_rule.rb +30 -9
  23. data/lib/ice_cube/rules/yearly_rule.rb +9 -0
  24. data/lib/ice_cube/schedule.rb +30 -29
  25. data/lib/ice_cube/single_occurrence_rule.rb +4 -0
  26. data/lib/ice_cube/time_util.rb +65 -46
  27. data/lib/ice_cube/validated_rule.rb +18 -24
  28. data/lib/ice_cube/validations/count.rb +1 -2
  29. data/lib/ice_cube/validations/daily_interval.rb +5 -1
  30. data/lib/ice_cube/validations/day.rb +6 -2
  31. data/lib/ice_cube/validations/day_of_month.rb +5 -0
  32. data/lib/ice_cube/validations/day_of_week.rb +1 -1
  33. data/lib/ice_cube/validations/hour_of_day.rb +23 -0
  34. data/lib/ice_cube/validations/hourly_interval.rb +2 -0
  35. data/lib/ice_cube/validations/minute_of_hour.rb +16 -0
  36. data/lib/ice_cube/validations/minutely_interval.rb +2 -0
  37. data/lib/ice_cube/validations/month_of_year.rb +6 -1
  38. data/lib/ice_cube/validations/monthly_interval.rb +4 -1
  39. data/lib/ice_cube/validations/schedule_lock.rb +4 -0
  40. data/lib/ice_cube/validations/second_of_minute.rb +19 -3
  41. data/lib/ice_cube/validations/secondly_interval.rb +2 -0
  42. data/lib/ice_cube/validations/until.rb +1 -2
  43. data/lib/ice_cube/validations/weekly_interval.rb +0 -2
  44. data/lib/ice_cube/version.rb +1 -1
  45. data/lib/ice_cube.rb +1 -3
  46. data/spec/spec_helper.rb +32 -9
  47. metadata +10 -7
@@ -340,9 +340,9 @@ module IceCube
340
340
  IcalParser.schedule_from_ical(ical, options)
341
341
  end
342
342
 
343
- # Convert the schedule to yaml
344
- def to_yaml(*args)
345
- YAML::dump(to_hash, *args)
343
+ # Hook for YAML.dump, enables to_yaml
344
+ def encode_with(coder)
345
+ coder.represent_object nil, to_hash
346
346
  end
347
347
 
348
348
  # Load the schedule from yaml
@@ -371,6 +371,7 @@ module IceCube
371
371
  end
372
372
  data
373
373
  end
374
+ alias_method :to_h, :to_hash
374
375
 
375
376
  # Load the schedule from a hash
376
377
  def self.from_hash(original_hash, options = {})
@@ -383,9 +384,22 @@ module IceCube
383
384
  # Determine if the schedule will end
384
385
  # @return [Boolean] true if ending, false if repeating forever
385
386
  def terminating?
386
- recurrence_rules.empty? || recurrence_rules.all?(&:terminating?)
387
+ @all_recurrence_rules.all?(&:terminating?)
387
388
  end
388
389
 
390
+ def hash
391
+ [
392
+ TimeUtil.hash(start_time), duration,
393
+ *@all_recurrence_rules.map(&:hash).sort!,
394
+ *@all_exception_rules.map(&:hash).sort!
395
+ ].hash
396
+ end
397
+
398
+ def eql?(other)
399
+ self.hash == other.hash
400
+ end
401
+ alias == eql?
402
+
389
403
  def self.dump(schedule)
390
404
  return schedule if schedule.nil? || schedule == ""
391
405
  schedule.to_yaml
@@ -407,31 +421,24 @@ module IceCube
407
421
  # Find all of the occurrences for the schedule between opening_time
408
422
  # and closing_time
409
423
  # Iteration is unrolled in pairs to skip duplicate times in end of DST
410
- def enumerate_occurrences(opening_time, closing_time = nil, options = {}, &block)
424
+ def enumerate_occurrences(opening_time, closing_time = nil, options = {})
411
425
  opening_time = TimeUtil.match_zone(opening_time, start_time)
412
426
  closing_time = TimeUtil.match_zone(closing_time, start_time)
413
- opening_time += start_time.subsec - opening_time.subsec rescue 0
427
+ opening_time += TimeUtil.subsec(start_time) - TimeUtil.subsec(opening_time)
414
428
  opening_time = start_time if opening_time < start_time
415
429
  spans = options[:spans] == true && duration != 0
416
430
  Enumerator.new do |yielder|
417
431
  reset
418
- t1 = full_required? ? start_time : opening_time - (spans ? duration : 0)
432
+ t1 = full_required? ? start_time : opening_time
433
+ t1 -= duration if spans
434
+ t1 = start_time if t1 < start_time
419
435
  loop do
420
436
  break unless (t0 = next_time(t1, closing_time))
421
437
  break if closing_time && t0 > closing_time
422
438
  if (spans ? (t0.end_time > opening_time) : (t0 >= opening_time))
423
- yielder << (block_given? ? block.call(t0) : t0)
424
- end
425
- break unless (t1 = next_time(t0 + 1, closing_time))
426
- break if closing_time && t1 > closing_time
427
- if TimeUtil.same_clock?(t0, t1) && recurrence_rules.any?(&:dst_adjust?)
428
- wind_back_dst
429
- next (t1 += 1)
439
+ yielder << (block_given? ? yield(t0) : t0)
430
440
  end
431
- if (spans ? (t1.end_time > opening_time) : (t1 >= opening_time))
432
- yielder << (block_given? ? block.call(t1) : t1)
433
- end
434
- next (t1 += 1)
441
+ t1 = t0 + 1
435
442
  end
436
443
  end
437
444
  end
@@ -439,15 +446,15 @@ module IceCube
439
446
  # Get the next time after (or including) a specific time
440
447
  def next_time(time, closing_time)
441
448
  loop do
442
- min_time = recurrence_rules_with_implicit_start_occurrence.reduce(nil) do |min_time, rule|
449
+ min_time = recurrence_rules_with_implicit_start_occurrence.reduce(nil) do |best_time, rule|
443
450
  begin
444
- new_time = rule.next_time(time, start_time, min_time || closing_time)
445
- [min_time, new_time].compact.min
451
+ new_time = rule.next_time(time, start_time, best_time || closing_time)
452
+ [best_time, new_time].compact.min
446
453
  rescue StopIteration
447
- min_time
454
+ best_time
448
455
  end
449
456
  end
450
- break nil unless min_time
457
+ break unless min_time
451
458
  next (time = min_time + 1) if exception_time?(min_time)
452
459
  break Occurrence.new(min_time, min_time + duration)
453
460
  end
@@ -498,12 +505,6 @@ module IceCube
498
505
  end
499
506
  end
500
507
 
501
- def wind_back_dst
502
- recurrence_rules.each do |rule|
503
- rule.skipped_for_dst
504
- end
505
- end
506
-
507
508
  end
508
509
 
509
510
  end
@@ -23,6 +23,10 @@ module IceCube
23
23
  { :time => time }
24
24
  end
25
25
 
26
+ def full_required?
27
+ false
28
+ end
29
+
26
30
  end
27
31
 
28
32
  end
@@ -47,7 +47,7 @@ module IceCube
47
47
  time.in_time_zone(reference.time_zone)
48
48
  else
49
49
  if reference.utc?
50
- time.utc
50
+ time.getgm
51
51
  elsif reference.zone
52
52
  time.getlocal
53
53
  else
@@ -89,18 +89,27 @@ module IceCube
89
89
 
90
90
  # Serialize a time appropriate for storing
91
91
  def self.serialize_time(time)
92
- if time.respond_to?(:time_zone)
93
- {:time => time.utc, :zone => time.time_zone.name}
94
- elsif time.is_a?(Time)
95
- time
92
+ case time
93
+ when Time, Date
94
+ if time.respond_to?(:time_zone)
95
+ {:time => time.utc, :zone => time.time_zone.name}
96
+ else
97
+ time
98
+ end
99
+ when DateTime
100
+ Time.local(time.year, time.month, time.day, time.hour, time.min, time.sec)
101
+ else
102
+ raise ArgumentError, "cannot serialize #{time.inspect}, expected a Time"
96
103
  end
97
104
  end
98
105
 
99
106
  # Deserialize a time serialized with serialize_time or in ISO8601 string format
100
107
  def self.deserialize_time(time_or_hash)
101
108
  case time_or_hash
102
- when Time
109
+ when Time, Date
103
110
  time_or_hash
111
+ when DateTime
112
+ Time.local(time.year, time.month, time.day, time.hour, time.min, time.sec)
104
113
  when Hash
105
114
  hash = FlexibleHash.new(time_or_hash)
106
115
  hash[:time].in_time_zone(hash[:zone])
@@ -109,6 +118,14 @@ module IceCube
109
118
  end
110
119
  end
111
120
 
121
+ # Get a more precise equality for time objects
122
+ # Ruby provides a Time#hash method, but it fails to account for UTC
123
+ # offset (so the current date may be different) or DST rules (so the
124
+ # hour may be wrong for different schedule occurrences)
125
+ def self.hash(time)
126
+ [time, time.utc_offset, time.zone].hash
127
+ end
128
+
112
129
  # Check the deserialized time offset string against actual local time
113
130
  # offset to try and preserve the original offset for plain Ruby Time. If
114
131
  # the offset is the same as local we can assume the same original zone and
@@ -153,20 +170,13 @@ module IceCube
153
170
 
154
171
  # Convert wday number to day symbol
155
172
  def self.wday_to_sym(wday)
156
- return sym = wday if DAYS.keys.include? wday
173
+ return wday if DAYS.keys.include? wday
157
174
  DAYS.invert.fetch(wday) do |i|
158
175
  raise ArgumentError, "Expecting Integer value for weekday. " \
159
176
  "No such wday number: #{i.inspect}"
160
177
  end
161
178
  end
162
179
 
163
- # Convert a symbol to an ical day (SU, MO)
164
- def self.week_start(sym)
165
- raise ArgumentError, "Invalid day: #{str}" unless DAYS.keys.include?(sym)
166
- day = sym.to_s.upcase[0..1]
167
- day
168
- end
169
-
170
180
  # Convert weekday from base sunday to the schedule's week start.
171
181
  def self.normalize_wday(wday, week_start)
172
182
  (wday - sym_to_wday(week_start)) % 7
@@ -243,8 +253,19 @@ module IceCube
243
253
  end
244
254
  end
245
255
 
246
- def self.same_clock?(t1, t2)
247
- CLOCK_VALUES.all? { |i| t1.send(i) == t2.send(i) }
256
+ # Handle discrepancies between various time types
257
+ # - Time has subsec
258
+ # - DateTime does not
259
+ # - ActiveSupport::TimeWithZone can wrap either type, depending on version
260
+ # or if `parse` or `now`/`local` was used to build it.
261
+ def self.subsec(time)
262
+ if time.respond_to?(:subsec)
263
+ time.subsec
264
+ elsif time.respond_to?(:sec_fraction)
265
+ time.sec_fraction
266
+ else
267
+ 0.0
268
+ end
248
269
  end
249
270
 
250
271
  # A utility class for safely moving time around
@@ -252,27 +273,32 @@ module IceCube
252
273
 
253
274
  def initialize(time, dst_adjust = true)
254
275
  @dst_adjust = dst_adjust
255
- @time = time
276
+ @base = time
277
+ if dst_adjust
278
+ @time = Time.utc(time.year, time.month, time.day, time.hour, time.min, time.sec + TimeUtil.subsec(time))
279
+ else
280
+ @time = time
281
+ end
256
282
  end
257
283
 
258
- # Get the wrapper time back
284
+ # Get the wrapped time back in its original zone & format
259
285
  def to_time
260
- @time
286
+ return @time unless @dst_adjust
287
+ parts = @time.year, @time.month, @time.day, @time.hour, @time.min, @time.sec + @time.subsec
288
+ TimeUtil.build_in_zone(parts, @base)
261
289
  end
262
290
 
263
291
  # DST-safely add an interval of time to the wrapped time
264
292
  def add(type, val)
265
293
  type = :day if type == :wday
266
- adjust do
267
- @time += case type
268
- when :year then TimeUtil.days_in_n_years(@time, val) * ONE_DAY
269
- when :month then TimeUtil.days_in_n_months(@time, val) * ONE_DAY
270
- when :day then val * ONE_DAY
271
- when :hour then val * ONE_HOUR
272
- when :min then val * ONE_MINUTE
273
- when :sec then val
274
- end
275
- end
294
+ @time += case type
295
+ when :year then TimeUtil.days_in_n_years(@time, val) * ONE_DAY
296
+ when :month then TimeUtil.days_in_n_months(@time, val) * ONE_DAY
297
+ when :day then val * ONE_DAY
298
+ when :hour then val * ONE_HOUR
299
+ when :min then val * ONE_MINUTE
300
+ when :sec then val
301
+ end
276
302
  end
277
303
 
278
304
  # Clear everything below a certain type
@@ -281,23 +307,20 @@ module IceCube
281
307
  type = :day if type == :wday
282
308
  CLEAR_ORDER.each do |ptype|
283
309
  break if ptype == type
284
- adjust do
285
- send(:"clear_#{ptype}")
286
- end
310
+ send :"clear_#{ptype}"
287
311
  end
288
312
  end
289
313
 
290
- private
314
+ def hour=(value)
315
+ @time += (value * ONE_HOUR) - (@time.hour * ONE_HOUR)
316
+ end
291
317
 
292
- def adjust(&block)
293
- if @dst_adjust
294
- off = @time.utc_offset
295
- yield
296
- diff = off - @time.utc_offset
297
- @time += diff if diff != 0
298
- else
299
- yield
300
- end
318
+ def min=(value)
319
+ @time += (value * ONE_MINUTE) - (@time.min * ONE_MINUTE)
320
+ end
321
+
322
+ def sec=(value)
323
+ @time += (value) - (@time.sec)
301
324
  end
302
325
 
303
326
  def clear_sec
@@ -326,10 +349,6 @@ module IceCube
326
349
  @time += ONE_DAY
327
350
  end
328
351
 
329
- def clear_year
330
- @time
331
- end
332
-
333
352
  end
334
353
 
335
354
  end
@@ -1,18 +1,11 @@
1
+ require 'ice_cube/input_alignment'
2
+
1
3
  module IceCube
2
4
 
3
5
  class ValidatedRule < Rule
4
6
 
5
7
  include Validations::ScheduleLock
6
8
 
7
- include Validations::HourOfDay
8
- include Validations::MinuteOfHour
9
- include Validations::SecondOfMinute
10
- include Validations::DayOfMonth
11
- include Validations::DayOfWeek
12
- include Validations::Day
13
- include Validations::MonthOfYear
14
- include Validations::DayOfYear
15
-
16
9
  include Validations::Count
17
10
  include Validations::Until
18
11
 
@@ -51,15 +44,14 @@ module IceCube
51
44
  Array(@validations[base_interval_validation.type])
52
45
  end
53
46
 
54
- def base_interval_type
55
- base_interval_validation.type
56
- end
57
-
58
47
  # Compute the next time after (or including) the specified time in respect
59
48
  # to the given start time
60
49
  def next_time(time, start_time, closing_time)
61
50
  @time = time
62
- @start_time ||= realign(time, start_time)
51
+ unless @start_time
52
+ @start_time = realign(time, start_time)
53
+ @time = @start_time if @time < @start_time
54
+ end
63
55
 
64
56
  return nil unless find_acceptable_time_before(closing_time)
65
57
 
@@ -71,17 +63,13 @@ module IceCube
71
63
  start_time
72
64
  end
73
65
 
74
- def skipped_for_dst
75
- @uses -= 1 if @uses > 0
76
- end
77
-
78
- def dst_adjust?
79
- @validations[:interval].any? &:dst_adjust?
66
+ def full_required?
67
+ !occurrence_count.nil?
80
68
  end
81
69
 
82
70
  def to_s
83
71
  builder = StringBuilder.new
84
- @validations.each do |name, validations|
72
+ @validations.each_value do |validations|
85
73
  validations.each do |validation|
86
74
  validation.build_s(builder)
87
75
  end
@@ -91,7 +79,7 @@ module IceCube
91
79
 
92
80
  def to_hash
93
81
  builder = HashBuilder.new(self)
94
- @validations.each do |name, validations|
82
+ @validations.each_value do |validations|
95
83
  validations.each do |validation|
96
84
  validation.build_hash(builder)
97
85
  end
@@ -101,7 +89,7 @@ module IceCube
101
89
 
102
90
  def to_ical
103
91
  builder = IcalBuilder.new
104
- @validations.each do |name, validations|
92
+ @validations.each_value do |validations|
105
93
  validations.each do |validation|
106
94
  validation.build_ical(builder)
107
95
  end
@@ -134,7 +122,7 @@ module IceCube
134
122
 
135
123
  def normalized_interval(interval)
136
124
  int = interval.to_i
137
- raise ArgumentError, "'#{interval}' is not a valid input for interval. Please pass an integer." unless int > 0
125
+ raise ArgumentError, "'#{interval}' is not a valid input for interval. Please pass a postive integer." unless int > 0
138
126
  int
139
127
  end
140
128
 
@@ -190,6 +178,12 @@ module IceCube
190
178
  VALIDATION_ORDER & @validations.keys
191
179
  end
192
180
 
181
+ def verify_alignment(value, freq, rule_part)
182
+ InputAlignment.new(self, value, rule_part).verify(freq) do |error|
183
+ yield error
184
+ end
185
+ end
186
+
193
187
  end
194
188
 
195
189
  end
@@ -4,14 +4,13 @@ module IceCube
4
4
 
5
5
  # Value reader for limit
6
6
  def occurrence_count
7
- @count
7
+ (arr = @validations[:count]) && (val = arr[0]) && val.count
8
8
  end
9
9
 
10
10
  def count(max)
11
11
  unless max.nil? || max.is_a?(Integer)
12
12
  raise ArgumentError, "Expecting Integer or nil value for count, got #{max.inspect}"
13
13
  end
14
- @count = max
15
14
  replace_validations_for(:count, max && [Validation.new(max, self)])
16
15
  self
17
16
  end
@@ -4,7 +4,11 @@ module IceCube
4
4
 
5
5
  # Add a new interval validation
6
6
  def interval(interval)
7
- @interval = normalized_interval(interval)
7
+ interval = normalized_interval(interval)
8
+ verify_alignment(interval, :wday, :interval) { |error| raise error }
9
+ verify_alignment(interval, :day, :interval) { |error| raise error }
10
+
11
+ @interval = interval
8
12
  replace_validations_for(:interval, [Validation.new(@interval)])
9
13
  clobber_base_validations(:wday, :day)
10
14
  self
@@ -1,5 +1,3 @@
1
- require 'date'
2
-
3
1
  module IceCube
4
2
 
5
3
  module Validations::Day
@@ -12,6 +10,8 @@ module IceCube
12
10
  raise ArgumentError, "expecting Integer or Symbol value for day, got #{day.inspect}"
13
11
  end
14
12
  day = TimeUtil.sym_to_wday(day)
13
+ verify_alignment(day, :wday, :day) { |error| raise error }
14
+
15
15
  validations_for(:day) << Validation.new(day)
16
16
  end
17
17
  clobber_base_validations(:wday, :day)
@@ -27,6 +27,10 @@ module IceCube
27
27
  @day = day
28
28
  end
29
29
 
30
+ def key
31
+ :day
32
+ end
33
+
30
34
  def type
31
35
  :wday
32
36
  end
@@ -7,6 +7,7 @@ module IceCube
7
7
  unless day.is_a?(Integer)
8
8
  raise ArgumentError, "expecting Integer value for day, got #{day.inspect}"
9
9
  end
10
+ verify_alignment(day, :day, :day_of_month) { |error| raise error }
10
11
  validations_for(:day_of_month) << Validation.new(day)
11
12
  end
12
13
  clobber_base_validations(:day, :wday)
@@ -22,6 +23,10 @@ module IceCube
22
23
  @day = day
23
24
  end
24
25
 
26
+ def key
27
+ :day_of_month
28
+ end
29
+
25
30
  def type
26
31
  :day
27
32
  end
@@ -48,7 +48,7 @@ module IceCube
48
48
  builder.piece(:day_of_week) << IceCube::I18n.t(
49
49
  'ice_cube.days_of_week',
50
50
  segments: StringBuilder.nice_number(occ),
51
- day: IceCube::I18n.t('ice_cube.date.day_names')[day]
51
+ day: IceCube::I18n.t('date.day_names')[day]
52
52
  )
53
53
  end
54
54
 
@@ -8,12 +8,31 @@ module IceCube
8
8
  unless hour.is_a?(Integer)
9
9
  raise ArgumentError, "expecting Integer value for hour, got #{hour.inspect}"
10
10
  end
11
+
12
+ verify_alignment(hour, :hour, :hour_of_day) { |error| raise error }
13
+
11
14
  validations_for(:hour_of_day) << Validation.new(hour)
12
15
  end
13
16
  clobber_base_validations(:hour)
14
17
  self
15
18
  end
16
19
 
20
+ def realign(opening_time, start_time)
21
+ return super unless validations[:hour_of_day]
22
+ freq = base_interval_validation.interval
23
+
24
+ first_hour = Array(validations[:hour_of_day]).min_by(&:value)
25
+ time = TimeUtil::TimeWrapper.new(start_time, false)
26
+ if freq > 1 && base_interval_validation.type == :hour
27
+ offset = first_hour.validate(opening_time, start_time)
28
+ time.add(:hour, offset - freq)
29
+ else
30
+ time.hour = first_hour.value
31
+ end
32
+
33
+ super opening_time, time.to_time
34
+ end
35
+
17
36
  class Validation < Validations::FixedValue
18
37
 
19
38
  attr_reader :hour
@@ -23,6 +42,10 @@ module IceCube
23
42
  @hour = hour
24
43
  end
25
44
 
45
+ def key
46
+ :hour_of_day
47
+ end
48
+
26
49
  def type
27
50
  :hour
28
51
  end
@@ -3,6 +3,8 @@ module IceCube
3
3
  module Validations::HourlyInterval
4
4
 
5
5
  def interval(interval)
6
+ verify_alignment(interval, :hour, :interval) { |error| raise error }
7
+
6
8
  @interval = normalized_interval(interval)
7
9
  replace_validations_for(:interval, [Validation.new(@interval)])
8
10
  clobber_base_validations(:hour)
@@ -7,12 +7,24 @@ module IceCube
7
7
  unless minute.is_a?(Integer)
8
8
  raise ArgumentError, "expecting Integer value for minute, got #{minute.inspect}"
9
9
  end
10
+
11
+ verify_alignment(minute, :min, :minute_of_hour) { |error| raise error }
12
+
10
13
  validations_for(:minute_of_hour) << Validation.new(minute)
11
14
  end
12
15
  clobber_base_validations(:min)
13
16
  self
14
17
  end
15
18
 
19
+ def realign(opening_time, start_time)
20
+ return super unless validations[:minute_of_hour]
21
+
22
+ first_minute = validations[:minute_of_hour].min_by(&:value)
23
+ time = TimeUtil::TimeWrapper.new(start_time, false)
24
+ time.min = first_minute.value
25
+ super opening_time, time.to_time
26
+ end
27
+
16
28
  class Validation < Validations::FixedValue
17
29
 
18
30
  attr_reader :minute
@@ -22,6 +34,10 @@ module IceCube
22
34
  @minute = minute
23
35
  end
24
36
 
37
+ def key
38
+ :minute_of_hour
39
+ end
40
+
25
41
  def type
26
42
  :min
27
43
  end
@@ -3,6 +3,8 @@ module IceCube
3
3
  module Validations::MinutelyInterval
4
4
 
5
5
  def interval(interval)
6
+ verify_alignment(interval, :min, :interval) { |error| raise error }
7
+
6
8
  @interval = normalized_interval(interval)
7
9
  replace_validations_for(:interval, [Validation.new(@interval)])
8
10
  clobber_base_validations(:min)
@@ -8,6 +8,7 @@ module IceCube
8
8
  raise ArgumentError, "expecting Integer or Symbol value for month, got #{month.inspect}"
9
9
  end
10
10
  month = TimeUtil.sym_to_month(month)
11
+ verify_alignment(month, :month, :month_of_year) { |error| raise error }
11
12
  validations_for(:month_of_year) << Validation.new(month)
12
13
  end
13
14
  clobber_base_validations :month
@@ -23,6 +24,10 @@ module IceCube
23
24
  @month = month
24
25
  end
25
26
 
27
+ def key
28
+ :month_of_year
29
+ end
30
+
26
31
  def type
27
32
  :month
28
33
  end
@@ -32,7 +37,7 @@ module IceCube
32
37
  end
33
38
 
34
39
  def build_s(builder)
35
- builder.piece(:month_of_year) << IceCube::I18n.t("ice_cube.date.month_names")[month]
40
+ builder.piece(:month_of_year) << IceCube::I18n.t("date.month_names")[month]
36
41
  end
37
42
 
38
43
  def build_hash(builder)
@@ -3,7 +3,10 @@ module IceCube
3
3
  module Validations::MonthlyInterval
4
4
 
5
5
  def interval(interval)
6
- @interval = normalized_interval(interval)
6
+ interval = normalized_interval(interval)
7
+ verify_alignment(interval, :month, :interval) { |error| raise error }
8
+
9
+ @interval = interval
7
10
  replace_validations_for(:interval, [Validation.new(@interval)])
8
11
  clobber_base_validations(:month)
9
12
  self
@@ -20,6 +20,10 @@ module IceCube
20
20
  @type = type
21
21
  end
22
22
 
23
+ def key
24
+ :base
25
+ end
26
+
23
27
  def dst_adjust?
24
28
  case @type
25
29
  when :sec, :min then false