chronic 0.2.0 → 0.3.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.
Files changed (58) hide show
  1. data/HISTORY.md +76 -0
  2. data/LICENSE +21 -0
  3. data/Manifest.txt +2 -0
  4. data/README.md +165 -0
  5. data/Rakefile +137 -32
  6. data/benchmark/benchmark.rb +13 -0
  7. data/chronic.gemspec +85 -0
  8. data/lib/chronic/chronic.rb +60 -50
  9. data/lib/chronic/grabber.rb +2 -2
  10. data/lib/chronic/handlers.rb +221 -111
  11. data/lib/{numerizer → chronic/numerizer}/numerizer.rb +17 -23
  12. data/lib/chronic/ordinal.rb +6 -6
  13. data/lib/chronic/pointer.rb +3 -3
  14. data/lib/chronic/repeater.rb +27 -12
  15. data/lib/chronic/repeaters/repeater_day.rb +23 -18
  16. data/lib/chronic/repeaters/repeater_day_name.rb +19 -14
  17. data/lib/chronic/repeaters/repeater_day_portion.rb +23 -22
  18. data/lib/chronic/repeaters/repeater_fortnight.rb +16 -11
  19. data/lib/chronic/repeaters/repeater_hour.rb +20 -15
  20. data/lib/chronic/repeaters/repeater_minute.rb +31 -16
  21. data/lib/chronic/repeaters/repeater_month.rb +33 -24
  22. data/lib/chronic/repeaters/repeater_month_name.rb +31 -26
  23. data/lib/chronic/repeaters/repeater_season.rb +136 -9
  24. data/lib/chronic/repeaters/repeater_season_name.rb +38 -17
  25. data/lib/chronic/repeaters/repeater_second.rb +15 -10
  26. data/lib/chronic/repeaters/repeater_time.rb +53 -43
  27. data/lib/chronic/repeaters/repeater_week.rb +16 -11
  28. data/lib/chronic/repeaters/repeater_weekday.rb +77 -0
  29. data/lib/chronic/repeaters/repeater_weekend.rb +14 -9
  30. data/lib/chronic/repeaters/repeater_year.rb +31 -25
  31. data/lib/chronic/scalar.rb +16 -14
  32. data/lib/chronic/separator.rb +25 -10
  33. data/lib/chronic/time_zone.rb +23 -0
  34. data/lib/chronic.rb +69 -14
  35. data/test/helper.rb +7 -0
  36. data/test/test_Chronic.rb +17 -18
  37. data/test/test_DaylightSavings.rb +118 -0
  38. data/test/test_Handler.rb +37 -38
  39. data/test/test_Numerizer.rb +8 -5
  40. data/test/test_RepeaterDayName.rb +15 -16
  41. data/test/test_RepeaterFortnight.rb +16 -17
  42. data/test/test_RepeaterHour.rb +18 -19
  43. data/test/test_RepeaterMinute.rb +34 -0
  44. data/test/test_RepeaterMonth.rb +16 -17
  45. data/test/test_RepeaterMonthName.rb +17 -18
  46. data/test/test_RepeaterTime.rb +20 -22
  47. data/test/test_RepeaterWeek.rb +16 -17
  48. data/test/test_RepeaterWeekday.rb +55 -0
  49. data/test/test_RepeaterWeekend.rb +21 -22
  50. data/test/test_RepeaterYear.rb +17 -18
  51. data/test/test_Span.rb +5 -6
  52. data/test/test_Time.rb +49 -0
  53. data/test/test_Token.rb +5 -6
  54. data/test/test_parsing.rb +338 -178
  55. metadata +78 -50
  56. data/History.txt +0 -38
  57. data/README.txt +0 -149
  58. data/test/suite.rb +0 -9
@@ -9,32 +9,32 @@ module Chronic
9
9
  end
10
10
  tokens
11
11
  end
12
-
12
+
13
13
  def self.scan_for_ordinals(token)
14
14
  if token.word =~ /^(\d*)(st|nd|rd|th)$/
15
15
  return Ordinal.new($1.to_i)
16
16
  end
17
17
  return nil
18
18
  end
19
-
19
+
20
20
  def self.scan_for_days(token)
21
21
  if token.word =~ /^(\d*)(st|nd|rd|th)$/
22
- unless $1.to_i > 31
22
+ unless $1.to_i > 31 || $1.to_i < 1
23
23
  return OrdinalDay.new(token.word.to_i)
24
24
  end
25
25
  end
26
26
  return nil
27
27
  end
28
-
28
+
29
29
  def to_s
30
30
  'ordinal'
31
31
  end
32
32
  end
33
-
33
+
34
34
  class OrdinalDay < Ordinal #:nodoc:
35
35
  def to_s
36
36
  super << '-day-' << @type.to_s
37
37
  end
38
38
  end
39
39
 
40
- end
40
+ end
@@ -8,7 +8,7 @@ module Chronic
8
8
  end
9
9
  tokens
10
10
  end
11
-
11
+
12
12
  def self.scan_for_all(token)
13
13
  scanner = {/\bpast\b/ => :past,
14
14
  /\bfuture\b/ => :future,
@@ -18,10 +18,10 @@ module Chronic
18
18
  end
19
19
  return nil
20
20
  end
21
-
21
+
22
22
  def to_s
23
23
  'pointer-' << @type.to_s
24
24
  end
25
25
  end
26
26
 
27
- end
27
+ end
@@ -2,6 +2,7 @@ class Chronic::Repeater < Chronic::Tag #:nodoc:
2
2
  def self.scan(tokens, options)
3
3
  # for each token
4
4
  tokens.each_index do |i|
5
+ if t = self.scan_for_season_names(tokens[i]) then tokens[i].tag(t); next end
5
6
  if t = self.scan_for_month_names(tokens[i]) then tokens[i].tag(t); next end
6
7
  if t = self.scan_for_day_names(tokens[i]) then tokens[i].tag(t); next end
7
8
  if t = self.scan_for_day_portions(tokens[i]) then tokens[i].tag(t); next end
@@ -10,7 +11,19 @@ class Chronic::Repeater < Chronic::Tag #:nodoc:
10
11
  end
11
12
  tokens
12
13
  end
13
-
14
+
15
+ def self.scan_for_season_names(token)
16
+ scanner = {/^springs?$/ => :spring,
17
+ /^summers?$/ => :summer,
18
+ /^(autumn)|(fall)s?$/ => :autumn,
19
+ /^winters?$/ => :winter}
20
+ scanner.keys.each do |scanner_item|
21
+ return Chronic::RepeaterSeasonName.new(scanner[scanner_item]) if scanner_item =~ token.word
22
+ end
23
+
24
+ return nil
25
+ end
26
+
14
27
  def self.scan_for_month_names(token)
15
28
  scanner = {/^jan\.?(uary)?$/ => :january,
16
29
  /^feb\.?(ruary)?$/ => :february,
@@ -29,10 +42,11 @@ class Chronic::Repeater < Chronic::Tag #:nodoc:
29
42
  end
30
43
  return nil
31
44
  end
32
-
45
+
33
46
  def self.scan_for_day_names(token)
34
47
  scanner = {/^m[ou]n(day)?$/ => :monday,
35
48
  /^t(ue|eu|oo|u|)s(day)?$/ => :tuesday,
49
+ /^tue$/ => :tuesday,
36
50
  /^we(dnes|nds|nns)day$/ => :wednesday,
37
51
  /^wed$/ => :wednesday,
38
52
  /^th(urs|ers)day$/ => :thursday,
@@ -45,7 +59,7 @@ class Chronic::Repeater < Chronic::Tag #:nodoc:
45
59
  end
46
60
  return nil
47
61
  end
48
-
62
+
49
63
  def self.scan_for_day_portions(token)
50
64
  scanner = {/^ams?$/ => :am,
51
65
  /^pms?$/ => :pm,
@@ -58,14 +72,14 @@ class Chronic::Repeater < Chronic::Tag #:nodoc:
58
72
  end
59
73
  return nil
60
74
  end
61
-
75
+
62
76
  def self.scan_for_times(token, options)
63
77
  if token.word =~ /^\d{1,2}(:?\d{2})?([\.:]?\d{2})?$/
64
78
  return Chronic::RepeaterTime.new(token.word, options)
65
79
  end
66
80
  return nil
67
81
  end
68
-
82
+
69
83
  def self.scan_for_units(token)
70
84
  scanner = {/^years?$/ => :year,
71
85
  /^seasons?$/ => :season,
@@ -73,6 +87,7 @@ class Chronic::Repeater < Chronic::Tag #:nodoc:
73
87
  /^fortnights?$/ => :fortnight,
74
88
  /^weeks?$/ => :week,
75
89
  /^weekends?$/ => :weekend,
90
+ /^(week|business)days?$/ => :weekday,
76
91
  /^days?$/ => :day,
77
92
  /^hours?$/ => :hour,
78
93
  /^minutes?$/ => :minute,
@@ -81,34 +96,34 @@ class Chronic::Repeater < Chronic::Tag #:nodoc:
81
96
  if scanner_item =~ token.word
82
97
  klass_name = 'Chronic::Repeater' + scanner[scanner_item].to_s.capitalize
83
98
  klass = eval(klass_name)
84
- return klass.new(scanner[scanner_item])
99
+ return klass.new(scanner[scanner_item])
85
100
  end
86
101
  end
87
102
  return nil
88
103
  end
89
-
104
+
90
105
  def <=>(other)
91
106
  width <=> other.width
92
107
  end
93
-
108
+
94
109
  # returns the width (in seconds or months) of this repeatable.
95
110
  def width
96
111
  raise("Repeatable#width must be overridden in subclasses")
97
112
  end
98
-
113
+
99
114
  # returns the next occurance of this repeatable.
100
115
  def next(pointer)
101
116
  !@now.nil? || raise("Start point must be set before calling #next")
102
117
  [:future, :none, :past].include?(pointer) || raise("First argument 'pointer' must be one of :past or :future")
103
118
  #raise("Repeatable#next must be overridden in subclasses")
104
119
  end
105
-
120
+
106
121
  def this(pointer)
107
122
  !@now.nil? || raise("Start point must be set before calling #this")
108
123
  [:future, :past, :none].include?(pointer) || raise("First argument 'pointer' must be one of :past, :future, :none")
109
124
  end
110
-
125
+
111
126
  def to_s
112
127
  'repeater'
113
128
  end
114
- end
129
+ end
@@ -1,47 +1,52 @@
1
1
  class Chronic::RepeaterDay < Chronic::Repeater #:nodoc:
2
2
  DAY_SECONDS = 86_400 # (24 * 60 * 60)
3
-
3
+
4
+ def initialize(type)
5
+ super
6
+ @current_day_start = nil
7
+ end
8
+
4
9
  def next(pointer)
5
10
  super
6
-
11
+
7
12
  if !@current_day_start
8
- @current_day_start = Time.local(@now.year, @now.month, @now.day)
13
+ @current_day_start = Chronic.time_class.local(@now.year, @now.month, @now.day)
9
14
  end
10
-
15
+
11
16
  direction = pointer == :future ? 1 : -1
12
17
  @current_day_start += direction * DAY_SECONDS
13
-
18
+
14
19
  Chronic::Span.new(@current_day_start, @current_day_start + DAY_SECONDS)
15
20
  end
16
-
21
+
17
22
  def this(pointer = :future)
18
23
  super
19
-
24
+
20
25
  case pointer
21
26
  when :future
22
- day_begin = Time.local(@now.year, @now.month, @now.day, @now.hour + 1)
23
- day_end = Time.local(@now.year, @now.month, @now.day) + DAY_SECONDS
27
+ day_begin = Time.construct(@now.year, @now.month, @now.day, @now.hour + 1)
28
+ day_end = Time.construct(@now.year, @now.month, @now.day) + DAY_SECONDS
24
29
  when :past
25
- day_begin = Time.local(@now.year, @now.month, @now.day)
26
- day_end = Time.local(@now.year, @now.month, @now.day, @now.hour)
30
+ day_begin = Time.construct(@now.year, @now.month, @now.day)
31
+ day_end = Time.construct(@now.year, @now.month, @now.day, @now.hour)
27
32
  when :none
28
- day_begin = Time.local(@now.year, @now.month, @now.day)
29
- day_end = Time.local(@now.year, @now.month, @now.day) + DAY_SECONDS
33
+ day_begin = Time.construct(@now.year, @now.month, @now.day)
34
+ day_end = Time.construct(@now.year, @now.month, @now.day) + DAY_SECONDS
30
35
  end
31
-
36
+
32
37
  Chronic::Span.new(day_begin, day_end)
33
38
  end
34
-
39
+
35
40
  def offset(span, amount, pointer)
36
41
  direction = pointer == :future ? 1 : -1
37
42
  span + direction * amount * DAY_SECONDS
38
43
  end
39
-
44
+
40
45
  def width
41
46
  DAY_SECONDS
42
47
  end
43
-
48
+
44
49
  def to_s
45
50
  super << '-day'
46
51
  end
47
- end
52
+ end
@@ -1,46 +1,51 @@
1
1
  class Chronic::RepeaterDayName < Chronic::Repeater #:nodoc:
2
2
  DAY_SECONDS = 86400 # (24 * 60 * 60)
3
-
3
+
4
+ def initialize(type)
5
+ super
6
+ @current_day_start = nil
7
+ end
8
+
4
9
  def next(pointer)
5
10
  super
6
-
11
+
7
12
  direction = pointer == :future ? 1 : -1
8
-
13
+
9
14
  if !@current_day_start
10
- @current_day_start = Time.local(@now.year, @now.month, @now.day)
15
+ @current_day_start = Time.construct(@now.year, @now.month, @now.day)
11
16
  @current_day_start += direction * DAY_SECONDS
12
17
 
13
18
  day_num = symbol_to_number(@type)
14
-
19
+
15
20
  while @current_day_start.wday != day_num
16
21
  @current_day_start += direction * DAY_SECONDS
17
22
  end
18
23
  else
19
24
  @current_day_start += direction * 7 * DAY_SECONDS
20
25
  end
21
-
26
+
22
27
  Chronic::Span.new(@current_day_start, @current_day_start + DAY_SECONDS)
23
28
  end
24
-
29
+
25
30
  def this(pointer = :future)
26
31
  super
27
-
32
+
28
33
  pointer = :future if pointer == :none
29
34
  self.next(pointer)
30
35
  end
31
-
36
+
32
37
  def width
33
38
  DAY_SECONDS
34
39
  end
35
-
40
+
36
41
  def to_s
37
- super << '-dayofweek-' << @type.to_s
42
+ super << '-dayname-' << @type.to_s
38
43
  end
39
-
44
+
40
45
  private
41
-
46
+
42
47
  def symbol_to_number(sym)
43
48
  lookup = {:sunday => 0, :monday => 1, :tuesday => 2, :wednesday => 3, :thursday => 4, :friday => 5, :saturday => 6}
44
49
  lookup[sym] || raise("Invalid symbol specified")
45
50
  end
46
- end
51
+ end
@@ -3,15 +3,16 @@ class Chronic::RepeaterDayPortion < Chronic::Repeater #:nodoc:
3
3
  @@afternoon = (13 * 60 * 60)..(17 * 60 * 60) # 1pm-5pm
4
4
  @@evening = (17 * 60 * 60)..(20 * 60 * 60) # 5pm-8pm
5
5
  @@night = (20 * 60 * 60)..(24 * 60 * 60) # 8pm-12pm
6
-
6
+
7
7
  def initialize(type)
8
8
  super
9
-
9
+ @current_span = nil
10
+
10
11
  if type.kind_of? Integer
11
12
  @range = (@type * 60 * 60)..((@type + 12) * 60 * 60)
12
13
  else
13
- lookup = {:am => 1..(12 * 60 * 60),
14
- :pm => (12 * 60 * 60)..(24 * 60 * 60),
14
+ lookup = {:am => 0..(12 * 60 * 60 - 1),
15
+ :pm => (12 * 60 * 60)..(24 * 60 * 60 - 1),
15
16
  :morning => @@morning,
16
17
  :afternoon => @@afternoon,
17
18
  :evening => @@evening,
@@ -21,37 +22,37 @@ class Chronic::RepeaterDayPortion < Chronic::Repeater #:nodoc:
21
22
  end
22
23
  @range || raise("Range should have been set by now")
23
24
  end
24
-
25
+
25
26
  def next(pointer)
26
27
  super
27
-
28
+
28
29
  full_day = 60 * 60 * 24
29
-
30
+
30
31
  if !@current_span
31
- now_seconds = @now - Time.local(@now.year, @now.month, @now.day)
32
+ now_seconds = @now - Time.construct(@now.year, @now.month, @now.day)
32
33
  if now_seconds < @range.begin
33
34
  case pointer
34
35
  when :future
35
- range_start = Time.local(@now.year, @now.month, @now.day) + @range.begin
36
+ range_start = Time.construct(@now.year, @now.month, @now.day) + @range.begin
36
37
  when :past
37
- range_start = Time.local(@now.year, @now.month, @now.day) - full_day + @range.begin
38
+ range_start = Time.construct(@now.year, @now.month, @now.day) - full_day + @range.begin
38
39
  end
39
40
  elsif now_seconds > @range.end
40
41
  case pointer
41
42
  when :future
42
- range_start = Time.local(@now.year, @now.month, @now.day) + full_day + @range.begin
43
+ range_start = Time.construct(@now.year, @now.month, @now.day) + full_day + @range.begin
43
44
  when :past
44
- range_start = Time.local(@now.year, @now.month, @now.day) + @range.begin
45
+ range_start = Time.construct(@now.year, @now.month, @now.day) + @range.begin
45
46
  end
46
47
  else
47
48
  case pointer
48
49
  when :future
49
- range_start = Time.local(@now.year, @now.month, @now.day) + full_day + @range.begin
50
+ range_start = Time.construct(@now.year, @now.month, @now.day) + full_day + @range.begin
50
51
  when :past
51
- range_start = Time.local(@now.year, @now.month, @now.day) - full_day + @range.begin
52
+ range_start = Time.construct(@now.year, @now.month, @now.day) - full_day + @range.begin
52
53
  end
53
54
  end
54
-
55
+
55
56
  @current_span = Chronic::Span.new(range_start, range_start + (@range.end - @range.begin))
56
57
  else
57
58
  case pointer
@@ -62,21 +63,21 @@ class Chronic::RepeaterDayPortion < Chronic::Repeater #:nodoc:
62
63
  end
63
64
  end
64
65
  end
65
-
66
+
66
67
  def this(context = :future)
67
68
  super
68
-
69
- range_start = Time.local(@now.year, @now.month, @now.day) + @range.begin
69
+
70
+ range_start = Time.construct(@now.year, @now.month, @now.day) + @range.begin
70
71
  @current_span = Chronic::Span.new(range_start, range_start + (@range.end - @range.begin))
71
72
  end
72
-
73
+
73
74
  def offset(span, amount, pointer)
74
75
  @now = span.begin
75
76
  portion_span = self.next(pointer)
76
77
  direction = pointer == :future ? 1 : -1
77
78
  portion_span + (direction * (amount - 1) * Chronic::RepeaterDay::DAY_SECONDS)
78
79
  end
79
-
80
+
80
81
  def width
81
82
  @range || raise("Range has not been set")
82
83
  return @current_span.width if @current_span
@@ -86,8 +87,8 @@ class Chronic::RepeaterDayPortion < Chronic::Repeater #:nodoc:
86
87
  @range.end - @range.begin
87
88
  end
88
89
  end
89
-
90
+
90
91
  def to_s
91
92
  super << '-dayportion-' << @type.to_s
92
93
  end
93
- end
94
+ end
@@ -1,9 +1,14 @@
1
1
  class Chronic::RepeaterFortnight < Chronic::Repeater #:nodoc:
2
2
  FORTNIGHT_SECONDS = 1_209_600 # (14 * 24 * 60 * 60)
3
-
3
+
4
+ def initialize(type)
5
+ super
6
+ @current_fortnight_start = nil
7
+ end
8
+
4
9
  def next(pointer)
5
10
  super
6
-
11
+
7
12
  if !@current_fortnight_start
8
13
  case pointer
9
14
  when :future
@@ -22,18 +27,18 @@ class Chronic::RepeaterFortnight < Chronic::Repeater #:nodoc:
22
27
  direction = pointer == :future ? 1 : -1
23
28
  @current_fortnight_start += direction * FORTNIGHT_SECONDS
24
29
  end
25
-
30
+
26
31
  Chronic::Span.new(@current_fortnight_start, @current_fortnight_start + FORTNIGHT_SECONDS)
27
32
  end
28
-
33
+
29
34
  def this(pointer = :future)
30
35
  super
31
-
36
+
32
37
  pointer = :future if pointer == :none
33
-
38
+
34
39
  case pointer
35
40
  when :future
36
- this_fortnight_start = Time.local(@now.year, @now.month, @now.day, @now.hour) + Chronic::RepeaterHour::HOUR_SECONDS
41
+ this_fortnight_start = Time.construct(@now.year, @now.month, @now.day, @now.hour) + Chronic::RepeaterHour::HOUR_SECONDS
37
42
  sunday_repeater = Chronic::RepeaterDayName.new(:sunday)
38
43
  sunday_repeater.start = @now
39
44
  sunday_repeater.this(:future)
@@ -41,7 +46,7 @@ class Chronic::RepeaterFortnight < Chronic::Repeater #:nodoc:
41
46
  this_fortnight_end = this_sunday_span.begin
42
47
  Chronic::Span.new(this_fortnight_start, this_fortnight_end)
43
48
  when :past
44
- this_fortnight_end = Time.local(@now.year, @now.month, @now.day, @now.hour)
49
+ this_fortnight_end = Time.construct(@now.year, @now.month, @now.day, @now.hour)
45
50
  sunday_repeater = Chronic::RepeaterDayName.new(:sunday)
46
51
  sunday_repeater.start = @now
47
52
  last_sunday_span = sunday_repeater.next(:past)
@@ -49,7 +54,7 @@ class Chronic::RepeaterFortnight < Chronic::Repeater #:nodoc:
49
54
  Chronic::Span.new(this_fortnight_start, this_fortnight_end)
50
55
  end
51
56
  end
52
-
57
+
53
58
  def offset(span, amount, pointer)
54
59
  direction = pointer == :future ? 1 : -1
55
60
  span + direction * amount * FORTNIGHT_SECONDS
@@ -58,8 +63,8 @@ class Chronic::RepeaterFortnight < Chronic::Repeater #:nodoc:
58
63
  def width
59
64
  FORTNIGHT_SECONDS
60
65
  end
61
-
66
+
62
67
  def to_s
63
68
  super << '-fortnight'
64
69
  end
65
- end
70
+ end
@@ -1,52 +1,57 @@
1
1
  class Chronic::RepeaterHour < Chronic::Repeater #:nodoc:
2
2
  HOUR_SECONDS = 3600 # 60 * 60
3
-
3
+
4
+ def initialize(type)
5
+ super
6
+ @current_hour_start = nil
7
+ end
8
+
4
9
  def next(pointer)
5
10
  super
6
-
11
+
7
12
  if !@current_hour_start
8
13
  case pointer
9
14
  when :future
10
- @current_hour_start = Time.local(@now.year, @now.month, @now.day, @now.hour + 1)
15
+ @current_hour_start = Time.construct(@now.year, @now.month, @now.day, @now.hour + 1)
11
16
  when :past
12
- @current_hour_start = Time.local(@now.year, @now.month, @now.day, @now.hour - 1)
17
+ @current_hour_start = Time.construct(@now.year, @now.month, @now.day, @now.hour - 1)
13
18
  end
14
19
  else
15
20
  direction = pointer == :future ? 1 : -1
16
21
  @current_hour_start += direction * HOUR_SECONDS
17
22
  end
18
-
23
+
19
24
  Chronic::Span.new(@current_hour_start, @current_hour_start + HOUR_SECONDS)
20
25
  end
21
-
26
+
22
27
  def this(pointer = :future)
23
28
  super
24
-
29
+
25
30
  case pointer
26
31
  when :future
27
32
  hour_start = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min + 1)
28
33
  hour_end = Time.construct(@now.year, @now.month, @now.day, @now.hour + 1)
29
34
  when :past
30
- hour_start = Time.local(@now.year, @now.month, @now.day, @now.hour)
31
- hour_end = Time.local(@now.year, @now.month, @now.day, @now.hour, @now.min)
35
+ hour_start = Time.construct(@now.year, @now.month, @now.day, @now.hour)
36
+ hour_end = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
32
37
  when :none
33
- hour_start = Time.local(@now.year, @now.month, @now.day, @now.hour)
38
+ hour_start = Time.construct(@now.year, @now.month, @now.day, @now.hour)
34
39
  hour_end = hour_begin + HOUR_SECONDS
35
40
  end
36
-
41
+
37
42
  Chronic::Span.new(hour_start, hour_end)
38
43
  end
39
-
44
+
40
45
  def offset(span, amount, pointer)
41
46
  direction = pointer == :future ? 1 : -1
42
47
  span + direction * amount * HOUR_SECONDS
43
48
  end
44
-
49
+
45
50
  def width
46
51
  HOUR_SECONDS
47
52
  end
48
-
53
+
49
54
  def to_s
50
55
  super << '-hour'
51
56
  end
52
- end
57
+ end
@@ -1,42 +1,57 @@
1
1
  class Chronic::RepeaterMinute < Chronic::Repeater #:nodoc:
2
2
  MINUTE_SECONDS = 60
3
-
3
+
4
+ def initialize(type)
5
+ super
6
+ @current_minute_start = nil
7
+ end
8
+
4
9
  def next(pointer = :future)
5
10
  super
6
-
7
- direction = pointer == :future ? 1 : -1
8
-
9
- raise 'not implemented'
11
+
12
+ if !@current_minute_start
13
+ case pointer
14
+ when :future
15
+ @current_minute_start = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min + 1)
16
+ when :past
17
+ @current_minute_start = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min - 1)
18
+ end
19
+ else
20
+ direction = pointer == :future ? 1 : -1
21
+ @current_minute_start += direction * MINUTE_SECONDS
22
+ end
23
+
24
+ Chronic::Span.new(@current_minute_start, @current_minute_start + MINUTE_SECONDS)
10
25
  end
11
-
26
+
12
27
  def this(pointer = :future)
13
28
  super
14
-
29
+
15
30
  case pointer
16
31
  when :future
17
32
  minute_begin = @now
18
- minute_end = Time.local(@now.year, @now.month, @now.day, @now.hour, @now.min)
33
+ minute_end = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
19
34
  when :past
20
- minute_begin = Time.local(@now.year, @now.month, @now.day, @now.hour, @now.min)
35
+ minute_begin = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
21
36
  minute_end = @now
22
37
  when :none
23
- minute_begin = Time.local(@now.year, @now.month, @now.day, @now.hour, @now.min)
24
- minute_end = Time.local(@now.year, @now.month, @now.day, @now.hour, @now.min) + MINUTE_SECONDS
38
+ minute_begin = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
39
+ minute_end = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min) + MINUTE_SECONDS
25
40
  end
26
-
41
+
27
42
  Chronic::Span.new(minute_begin, minute_end)
28
43
  end
29
-
44
+
30
45
  def offset(span, amount, pointer)
31
46
  direction = pointer == :future ? 1 : -1
32
47
  span + direction * amount * MINUTE_SECONDS
33
48
  end
34
-
49
+
35
50
  def width
36
51
  MINUTE_SECONDS
37
52
  end
38
-
53
+
39
54
  def to_s
40
55
  super << '-minute'
41
56
  end
42
- end
57
+ end