chronic 0.1.5 → 0.6.5

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 (68) hide show
  1. data/.gemtest +0 -0
  2. data/.gitignore +5 -0
  3. data/.yardopts +3 -0
  4. data/HISTORY.md +180 -0
  5. data/LICENSE +21 -0
  6. data/README.md +176 -0
  7. data/Rakefile +39 -32
  8. data/chronic.gemspec +17 -0
  9. data/lib/chronic/chronic.rb +294 -208
  10. data/lib/chronic/grabber.rb +22 -17
  11. data/lib/chronic/handler.rb +90 -0
  12. data/lib/chronic/handlers.rb +365 -278
  13. data/lib/chronic/mini_date.rb +38 -0
  14. data/lib/chronic/numerizer.rb +121 -0
  15. data/lib/chronic/ordinal.rb +23 -19
  16. data/lib/chronic/pointer.rb +20 -17
  17. data/lib/chronic/repeater.rb +126 -105
  18. data/lib/chronic/repeaters/repeater_day.rb +49 -43
  19. data/lib/chronic/repeaters/repeater_day_name.rb +48 -42
  20. data/lib/chronic/repeaters/repeater_day_portion.rb +81 -80
  21. data/lib/chronic/repeaters/repeater_fortnight.rb +59 -53
  22. data/lib/chronic/repeaters/repeater_hour.rb +49 -43
  23. data/lib/chronic/repeaters/repeater_minute.rb +55 -39
  24. data/lib/chronic/repeaters/repeater_month.rb +77 -55
  25. data/lib/chronic/repeaters/repeater_month_name.rb +83 -82
  26. data/lib/chronic/repeaters/repeater_season.rb +107 -21
  27. data/lib/chronic/repeaters/repeater_season_name.rb +41 -22
  28. data/lib/chronic/repeaters/repeater_second.rb +39 -33
  29. data/lib/chronic/repeaters/repeater_time.rb +117 -103
  30. data/lib/chronic/repeaters/repeater_week.rb +63 -57
  31. data/lib/chronic/repeaters/repeater_weekday.rb +85 -0
  32. data/lib/chronic/repeaters/repeater_weekend.rb +64 -9
  33. data/lib/chronic/repeaters/repeater_year.rb +70 -51
  34. data/lib/chronic/scalar.rb +64 -29
  35. data/lib/chronic/season.rb +37 -0
  36. data/lib/chronic/separator.rb +50 -38
  37. data/lib/chronic/span.rb +31 -0
  38. data/lib/chronic/tag.rb +42 -0
  39. data/lib/chronic/time_zone.rb +30 -0
  40. data/lib/chronic/token.rb +45 -0
  41. data/lib/chronic.rb +86 -22
  42. data/test/helper.rb +6 -0
  43. data/test/test_Chronic.rb +118 -20
  44. data/test/test_DaylightSavings.rb +118 -0
  45. data/test/test_Handler.rb +36 -42
  46. data/test/test_MiniDate.rb +32 -0
  47. data/test/test_Numerizer.rb +72 -0
  48. data/test/test_RepeaterDayName.rb +15 -16
  49. data/test/test_RepeaterFortnight.rb +16 -17
  50. data/test/test_RepeaterHour.rb +22 -19
  51. data/test/test_RepeaterMinute.rb +34 -0
  52. data/test/test_RepeaterMonth.rb +20 -17
  53. data/test/test_RepeaterMonthName.rb +17 -18
  54. data/test/test_RepeaterSeason.rb +40 -0
  55. data/test/test_RepeaterTime.rb +20 -22
  56. data/test/test_RepeaterWeek.rb +16 -17
  57. data/test/test_RepeaterWeekday.rb +55 -0
  58. data/test/test_RepeaterWeekend.rb +74 -0
  59. data/test/test_RepeaterYear.rb +24 -18
  60. data/test/test_Span.rb +5 -6
  61. data/test/test_Token.rb +5 -6
  62. data/test/test_parsing.rb +743 -338
  63. metadata +81 -54
  64. data/History.txt +0 -29
  65. data/Manifest.txt +0 -43
  66. data/README.txt +0 -149
  67. data/test/parse_numbers.rb +0 -50
  68. data/test/suite.rb +0 -9
@@ -0,0 +1,38 @@
1
+ module Chronic
2
+ class MiniDate
3
+ attr_accessor :month, :day
4
+
5
+ def self.from_time(time)
6
+ new(time.month, time.day)
7
+ end
8
+
9
+ def initialize(month, day)
10
+ unless (1..12).include?(month)
11
+ raise ArgumentError, "1..12 are valid months"
12
+ end
13
+
14
+ @month = month
15
+ @day = day
16
+ end
17
+
18
+ def is_between?(md_start, md_end)
19
+ return false if (@month == md_start.month && @month == md_end.month) &&
20
+ (@day < md_start.day || @day > md_end.day)
21
+ return true if (@month == md_start.month && @day >= md_start.day) ||
22
+ (@month == md_end.month && @day <= md_end.day)
23
+
24
+ i = (md_start.month % 12) + 1
25
+
26
+ until i == md_end.month
27
+ return true if @month == i
28
+ i = (i % 12) + 1
29
+ end
30
+
31
+ return false
32
+ end
33
+
34
+ def equals?(other)
35
+ @month == other.month and @day == other.day
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,121 @@
1
+ require 'strscan'
2
+
3
+ module Chronic
4
+ class Numerizer
5
+
6
+ DIRECT_NUMS = [
7
+ ['eleven', '11'],
8
+ ['twelve', '12'],
9
+ ['thirteen', '13'],
10
+ ['fourteen', '14'],
11
+ ['fifteen', '15'],
12
+ ['sixteen', '16'],
13
+ ['seventeen', '17'],
14
+ ['eighteen', '18'],
15
+ ['nineteen', '19'],
16
+ ['ninteen', '19'], # Common mis-spelling
17
+ ['zero', '0'],
18
+ ['one', '1'],
19
+ ['two', '2'],
20
+ ['three', '3'],
21
+ ['four(\W|$)', '4\1'], # The weird regex is so that it matches four but not fourty
22
+ ['five', '5'],
23
+ ['six(\W|$)', '6\1'],
24
+ ['seven(\W|$)', '7\1'],
25
+ ['eight(\W|$)', '8\1'],
26
+ ['nine(\W|$)', '9\1'],
27
+ ['ten', '10'],
28
+ ['\ba[\b^$]', '1'] # doesn't make sense for an 'a' at the end to be a 1
29
+ ]
30
+
31
+ ORDINALS = [
32
+ ['first', '1'],
33
+ ['third', '3'],
34
+ ['fourth', '4'],
35
+ ['fifth', '5'],
36
+ ['sixth', '6'],
37
+ ['seventh', '7'],
38
+ ['eighth', '8'],
39
+ ['ninth', '9'],
40
+ ['tenth', '10']
41
+ ]
42
+
43
+ TEN_PREFIXES = [
44
+ ['twenty', 20],
45
+ ['thirty', 30],
46
+ ['forty', 40],
47
+ ['fourty', 40], # Common mis-spelling
48
+ ['fifty', 50],
49
+ ['sixty', 60],
50
+ ['seventy', 70],
51
+ ['eighty', 80],
52
+ ['ninety', 90]
53
+ ]
54
+
55
+ BIG_PREFIXES = [
56
+ ['hundred', 100],
57
+ ['thousand', 1000],
58
+ ['million', 1_000_000],
59
+ ['billion', 1_000_000_000],
60
+ ['trillion', 1_000_000_000_000],
61
+ ]
62
+
63
+ def self.numerize(string)
64
+ string = string.dup
65
+
66
+ # preprocess
67
+ string.gsub!(/ +|([^\d])-([^\d])/, '\1 \2') # will mutilate hyphenated-words but shouldn't matter for date extraction
68
+ string.gsub!(/a half/, 'haAlf') # take the 'a' out so it doesn't turn into a 1, save the half for the end
69
+
70
+ # easy/direct replacements
71
+
72
+ DIRECT_NUMS.each do |dn|
73
+ string.gsub!(/#{dn[0]}/i, '<num>' + dn[1])
74
+ end
75
+
76
+ ORDINALS.each do |on|
77
+ string.gsub!(/#{on[0]}/i, '<num>' + on[1] + on[0][-2, 2])
78
+ end
79
+
80
+ # ten, twenty, etc.
81
+
82
+ TEN_PREFIXES.each do |tp|
83
+ string.gsub!(/(?:#{tp[0]}) *<num>(\d(?=[^\d]|$))*/i) { '<num>' + (tp[1] + $1.to_i).to_s }
84
+ end
85
+
86
+ TEN_PREFIXES.each do |tp|
87
+ string.gsub!(/#{tp[0]}/i) { '<num>' + tp[1].to_s }
88
+ end
89
+
90
+ # hundreds, thousands, millions, etc.
91
+
92
+ BIG_PREFIXES.each do |bp|
93
+ string.gsub!(/(?:<num>)?(\d*) *#{bp[0]}/i) { '<num>' + (bp[1] * $1.to_i).to_s}
94
+ andition(string)
95
+ end
96
+
97
+ # fractional addition
98
+ # I'm not combining this with the previous block as using float addition complicates the strings
99
+ # (with extraneous .0's and such )
100
+ string.gsub!(/(\d+)(?: | and |-)*haAlf/i) { ($1.to_f + 0.5).to_s }
101
+
102
+ string.gsub(/<num>/, '')
103
+ end
104
+
105
+ class << self
106
+ private
107
+
108
+ def andition(string)
109
+ sc = StringScanner.new(string)
110
+
111
+ while sc.scan_until(/<num>(\d+)( | and )<num>(\d+)(?=[^\w]|$)/i)
112
+ if sc[2] =~ /and/ || sc[1].size > sc[3].size
113
+ string[(sc.pos - sc.matched_size)..(sc.pos-1)] = '<num>' + (sc[1].to_i + sc[3].to_i).to_s
114
+ sc.reset
115
+ end
116
+ end
117
+ end
118
+
119
+ end
120
+ end
121
+ end
@@ -1,40 +1,44 @@
1
1
  module Chronic
2
+ class Ordinal < Tag
2
3
 
3
- class Ordinal < Tag #:nodoc:
4
- def self.scan(tokens)
5
- # for each token
6
- tokens.each_index do |i|
7
- if t = self.scan_for_ordinals(tokens[i]) then tokens[i].tag(t) end
8
- if t = self.scan_for_days(tokens[i]) then tokens[i].tag(t) end
4
+ # Scan an Array of {Token}s and apply any necessary Ordinal tags to
5
+ # each token
6
+ #
7
+ # @param [Array<Token>] tokens Array of tokens to scan
8
+ # @param [Hash] options Options specified in {Chronic.parse}
9
+ # @return [Array] list of tokens
10
+ def self.scan(tokens, options)
11
+ tokens.each do |token|
12
+ if t = scan_for_ordinals(token) then token.tag(t) end
13
+ if t = scan_for_days(token) then token.tag(t) end
9
14
  end
10
- tokens
11
15
  end
12
-
16
+
17
+ # @param [Token] token
18
+ # @return [Ordinal, nil]
13
19
  def self.scan_for_ordinals(token)
14
- if token.word =~ /^(\d*)(st|nd|rd|th)$/
15
- return Ordinal.new($1.to_i)
16
- end
17
- return nil
20
+ Ordinal.new($1.to_i) if token.word =~ /^(\d*)(st|nd|rd|th)$/
18
21
  end
19
-
22
+
23
+ # @param [Token] token
24
+ # @return [OrdinalDay, nil]
20
25
  def self.scan_for_days(token)
21
26
  if token.word =~ /^(\d*)(st|nd|rd|th)$/
22
- unless $1.to_i > 31
23
- return OrdinalDay.new(token.word.to_i)
27
+ unless $1.to_i > 31 || $1.to_i < 1
28
+ OrdinalDay.new(token.word.to_i)
24
29
  end
25
30
  end
26
- return nil
27
31
  end
28
-
32
+
29
33
  def to_s
30
34
  'ordinal'
31
35
  end
32
36
  end
33
-
37
+
34
38
  class OrdinalDay < Ordinal #:nodoc:
35
39
  def to_s
36
40
  super << '-day-' << @type.to_s
37
41
  end
38
42
  end
39
43
 
40
- end
44
+ end
@@ -1,27 +1,30 @@
1
1
  module Chronic
2
+ class Pointer < Tag
2
3
 
3
- class Pointer < Tag #:nodoc:
4
- def self.scan(tokens)
5
- # for each token
6
- tokens.each_index do |i|
7
- if t = self.scan_for_all(tokens[i]) then tokens[i].tag(t) end
4
+ # Scan an Array of {Token}s and apply any necessary Pointer tags to
5
+ # each token
6
+ #
7
+ # @param [Array<Token>] tokens Array of tokens to scan
8
+ # @param [Hash] options Options specified in {Chronic.parse}
9
+ # @return [Array] list of tokens
10
+ def self.scan(tokens, options)
11
+ tokens.each do |token|
12
+ if t = scan_for_all(token) then token.tag(t) end
8
13
  end
9
- tokens
10
14
  end
11
-
15
+
16
+ # @param [Token] token
17
+ # @return [Pointer, nil]
12
18
  def self.scan_for_all(token)
13
- scanner = {/past/ => :past,
14
- /future/ => :future,
15
- /in/ => :future}
16
- scanner.keys.each do |scanner_item|
17
- return self.new(scanner[scanner_item]) if scanner_item =~ token.word
18
- end
19
- return nil
19
+ scan_for token, self,
20
+ {
21
+ /\bpast\b/ => :past,
22
+ /\b(?:future|in)\b/ => :future,
23
+ }
20
24
  end
21
-
25
+
22
26
  def to_s
23
27
  'pointer-' << @type.to_s
24
28
  end
25
29
  end
26
-
27
- end
30
+ end
@@ -1,114 +1,135 @@
1
- class Chronic::Repeater < Chronic::Tag #:nodoc:
2
- def self.scan(tokens, options)
3
- # for each token
4
- tokens.each_index do |i|
5
- if t = self.scan_for_month_names(tokens[i]) then tokens[i].tag(t); next end
6
- if t = self.scan_for_day_names(tokens[i]) then tokens[i].tag(t); next end
7
- if t = self.scan_for_day_portions(tokens[i]) then tokens[i].tag(t); next end
8
- if t = self.scan_for_times(tokens[i], options) then tokens[i].tag(t); next end
9
- if t = self.scan_for_units(tokens[i]) then tokens[i].tag(t); next end
1
+ module Chronic
2
+ class Repeater < Tag
3
+
4
+ # Scan an Array of {Token}s and apply any necessary Repeater tags to
5
+ # each token
6
+ #
7
+ # @param [Array<Token>] tokens Array of tokens to scan
8
+ # @param [Hash] options Options specified in {Chronic.parse}
9
+ # @return [Array] list of tokens
10
+ def self.scan(tokens, options)
11
+ tokens.each do |token|
12
+ if t = scan_for_season_names(token) then token.tag(t); next end
13
+ if t = scan_for_month_names(token) then token.tag(t); next end
14
+ if t = scan_for_day_names(token) then token.tag(t); next end
15
+ if t = scan_for_day_portions(token) then token.tag(t); next end
16
+ if t = scan_for_times(token) then token.tag(t); next end
17
+ if t = scan_for_units(token) then token.tag(t); next end
18
+ end
10
19
  end
11
- tokens
12
- end
13
-
14
- def self.scan_for_month_names(token)
15
- scanner = {/^jan\.?(uary)?$/ => :january,
16
- /^feb\.?(ruary)?$/ => :february,
17
- /^mar\.?(ch)?$/ => :march,
18
- /^apr\.?(il)?$/ => :april,
19
- /^may$/ => :may,
20
- /^jun\.?e?$/ => :june,
21
- /^jul\.?y?$/ => :july,
22
- /^aug\.?(ust)?$/ => :august,
23
- /^sep\.?(t\.?|tember)?$/ => :september,
24
- /^oct\.?(ober)?$/ => :october,
25
- /^nov\.?(ember)?$/ => :november,
26
- /^dec\.?(ember)?$/ => :december}
27
- scanner.keys.each do |scanner_item|
28
- return Chronic::RepeaterMonthName.new(scanner[scanner_item]) if scanner_item =~ token.word
20
+
21
+ # @param [Token] token
22
+ # @return [RepeaterSeasonName, nil]
23
+ def self.scan_for_season_names(token)
24
+ scan_for token, RepeaterSeasonName,
25
+ {
26
+ /^springs?$/ => :spring,
27
+ /^summers?$/ => :summer,
28
+ /^(autumn)|(fall)s?$/ => :autumn,
29
+ /^winters?$/ => :winter
30
+ }
29
31
  end
30
- return nil
31
- end
32
-
33
- def self.scan_for_day_names(token)
34
- scanner = {/^m[ou]n(day)?$/ => :monday,
35
- /^t(ue|eu|oo|u|)s(day)?$/ => :tuesday,
36
- /^we(dnes|nds|nns)day$/ => :wednesday,
37
- /^wed$/ => :wednesday,
38
- /^th(urs|ers)day$/ => :thursday,
39
- /^thu$/ => :thursday,
40
- /^fr[iy](day)?$/ => :friday,
41
- /^sat(t?[ue]rday)?$/ => :saturday,
42
- /^su[nm](day)?$/ => :sunday}
43
- scanner.keys.each do |scanner_item|
44
- return Chronic::RepeaterDayName.new(scanner[scanner_item]) if scanner_item =~ token.word
32
+
33
+ # @param [Token] token
34
+ # @return [RepeaterMonthName, nil]
35
+ def self.scan_for_month_names(token)
36
+ scan_for token, RepeaterMonthName,
37
+ {
38
+ /^jan\.?(uary)?$/ => :january,
39
+ /^feb\.?(ruary)?$/ => :february,
40
+ /^mar\.?(ch)?$/ => :march,
41
+ /^apr\.?(il)?$/ => :april,
42
+ /^may$/ => :may,
43
+ /^jun\.?e?$/ => :june,
44
+ /^jul\.?y?$/ => :july,
45
+ /^aug\.?(ust)?$/ => :august,
46
+ /^sep\.?(t\.?|tember)?$/ => :september,
47
+ /^oct\.?(ober)?$/ => :october,
48
+ /^nov\.?(ember)?$/ => :november,
49
+ /^dec\.?(ember)?$/ => :december
50
+ }
45
51
  end
46
- return nil
47
- end
48
-
49
- def self.scan_for_day_portions(token)
50
- scanner = {/^ams?$/ => :am,
51
- /^pms?$/ => :pm,
52
- /^mornings?$/ => :morning,
53
- /^afternoons?$/ => :afternoon,
54
- /^evenings?$/ => :evening,
55
- /^(night|nite)s?$/ => :night}
56
- scanner.keys.each do |scanner_item|
57
- return Chronic::RepeaterDayPortion.new(scanner[scanner_item]) if scanner_item =~ token.word
52
+
53
+ # @param [Token] token
54
+ # @return [RepeaterDayName, nil]
55
+ def self.scan_for_day_names(token)
56
+ scan_for token, RepeaterDayName,
57
+ {
58
+ /^m[ou]n(day)?$/ => :monday,
59
+ /^t(ue|eu|oo|u|)s?(day)?$/ => :tuesday,
60
+ /^we(d|dnes|nds|nns)(day)?$/ => :wednesday,
61
+ /^th(u(?:rs)?|ers)(day)?$/ => :thursday,
62
+ /^fr[iy](day)?$/ => :friday,
63
+ /^sat(t?[ue]rday)?$/ => :saturday,
64
+ /^su[nm](day)?$/ => :sunday
65
+ }
58
66
  end
59
- return nil
60
- end
61
-
62
- def self.scan_for_times(token, options)
63
- if token.word =~ /^\d{1,2}(:?\d{2})?([\.:]?\d{2})?$/
64
- return Chronic::RepeaterTime.new(token.word, options)
67
+
68
+ # @param [Token] token
69
+ # @return [RepeaterDayPortion, nil]
70
+ def self.scan_for_day_portions(token)
71
+ scan_for token, RepeaterDayPortion,
72
+ {
73
+ /^ams?$/ => :am,
74
+ /^pms?$/ => :pm,
75
+ /^mornings?$/ => :morning,
76
+ /^afternoons?$/ => :afternoon,
77
+ /^evenings?$/ => :evening,
78
+ /^(night|nite)s?$/ => :night
79
+ }
65
80
  end
66
- return nil
67
- end
68
-
69
- def self.scan_for_units(token)
70
- scanner = {/^years?$/ => :year,
71
- /^seasons?$/ => :season,
72
- /^months?$/ => :month,
73
- /^fortnights?$/ => :fortnight,
74
- /^weeks?$/ => :week,
75
- /^weekends?$/ => :weekends,
76
- /^days?$/ => :day,
77
- /^hours?$/ => :hour,
78
- /^minutes?$/ => :minute,
79
- /^seconds?$/ => :second}
80
- scanner.keys.each do |scanner_item|
81
- if scanner_item =~ token.word
82
- klass_name = 'Chronic::Repeater' + scanner[scanner_item].to_s.capitalize
83
- klass = eval(klass_name)
84
- return klass.new(scanner[scanner_item])
81
+
82
+ # @param [Token] token
83
+ # @return [RepeaterTime, nil]
84
+ def self.scan_for_times(token)
85
+ scan_for token, RepeaterTime, /^\d{1,2}(:?\d{2})?([\.:]?\d{2})?$/
86
+ end
87
+
88
+ # @param [Token] token
89
+ # @return [Repeater] A new instance of a subclass of Repeater
90
+ def self.scan_for_units(token)
91
+ {
92
+ /^years?$/ => :year,
93
+ /^seasons?$/ => :season,
94
+ /^months?$/ => :month,
95
+ /^fortnights?$/ => :fortnight,
96
+ /^weeks?$/ => :week,
97
+ /^weekends?$/ => :weekend,
98
+ /^(week|business)days?$/ => :weekday,
99
+ /^days?$/ => :day,
100
+ /^hours?$/ => :hour,
101
+ /^minutes?$/ => :minute,
102
+ /^seconds?$/ => :second
103
+ }.each do |item, symbol|
104
+ if item =~ token.word
105
+ klass_name = 'Repeater' + symbol.to_s.capitalize
106
+ klass = Chronic.const_get(klass_name)
107
+ return klass.new(symbol)
108
+ end
85
109
  end
110
+ return nil
111
+ end
112
+
113
+ def <=>(other)
114
+ width <=> other.width
115
+ end
116
+
117
+ # returns the width (in seconds or months) of this repeatable.
118
+ def width
119
+ raise("Repeater#width must be overridden in subclasses")
120
+ end
121
+
122
+ # returns the next occurance of this repeatable.
123
+ def next(pointer)
124
+ raise("Start point must be set before calling #next") unless @now
125
+ end
126
+
127
+ def this(pointer)
128
+ raise("Start point must be set before calling #this") unless @now
129
+ end
130
+
131
+ def to_s
132
+ 'repeater'
86
133
  end
87
- return nil
88
- end
89
-
90
- def <=>(other)
91
- width <=> other.width
92
- end
93
-
94
- # returns the width (in seconds or months) of this repeatable.
95
- def width
96
- raise("Repeatable#width must be overridden in subclasses")
97
- end
98
-
99
- # returns the next occurance of this repeatable.
100
- def next(pointer)
101
- !@now.nil? || raise("Start point must be set before calling #next")
102
- [:future, :none, :past].include?(pointer) || raise("First argument 'pointer' must be one of :past or :future")
103
- #raise("Repeatable#next must be overridden in subclasses")
104
- end
105
-
106
- def this(pointer)
107
- !@now.nil? || raise("Start point must be set before calling #next")
108
- [:future, :past, :none].include?(pointer) || raise("First argument 'pointer' must be one of :past, :future, :none")
109
- end
110
-
111
- def to_s
112
- 'repeater'
113
134
  end
114
135
  end
@@ -1,47 +1,53 @@
1
- class Chronic::RepeaterDay < Chronic::Repeater #:nodoc:
2
- DAY_SECONDS = 86_400 # (24 * 60 * 60)
3
-
4
- def next(pointer)
5
- super
6
-
7
- if !@current_day_start
8
- @current_day_start = Time.local(@now.year, @now.month, @now.day)
1
+ module Chronic
2
+ class RepeaterDay < Repeater #:nodoc:
3
+ DAY_SECONDS = 86_400 # (24 * 60 * 60)
4
+
5
+ def initialize(type)
6
+ super
9
7
  end
10
-
11
- direction = pointer == :future ? 1 : -1
12
- @current_day_start += direction * DAY_SECONDS
13
-
14
- Chronic::Span.new(@current_day_start, @current_day_start + DAY_SECONDS)
15
- end
16
-
17
- def this(pointer = :future)
18
- super
19
-
20
- case pointer
21
- 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
24
- 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)
27
- 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
8
+
9
+ def next(pointer)
10
+ super
11
+
12
+ if !@current_day_start
13
+ @current_day_start = Chronic.time_class.local(@now.year, @now.month, @now.day)
14
+ end
15
+
16
+ direction = pointer == :future ? 1 : -1
17
+ @current_day_start += direction * DAY_SECONDS
18
+
19
+ Span.new(@current_day_start, @current_day_start + DAY_SECONDS)
20
+ end
21
+
22
+ def this(pointer = :future)
23
+ super
24
+
25
+ case pointer
26
+ when :future
27
+ day_begin = Chronic.construct(@now.year, @now.month, @now.day, @now.hour)
28
+ day_end = Chronic.construct(@now.year, @now.month, @now.day) + DAY_SECONDS
29
+ when :past
30
+ day_begin = Chronic.construct(@now.year, @now.month, @now.day)
31
+ day_end = Chronic.construct(@now.year, @now.month, @now.day, @now.hour)
32
+ when :none
33
+ day_begin = Chronic.construct(@now.year, @now.month, @now.day)
34
+ day_end = Chronic.construct(@now.year, @now.month, @now.day) + DAY_SECONDS
35
+ end
36
+
37
+ Span.new(day_begin, day_end)
38
+ end
39
+
40
+ def offset(span, amount, pointer)
41
+ direction = pointer == :future ? 1 : -1
42
+ span + direction * amount * DAY_SECONDS
43
+ end
44
+
45
+ def width
46
+ DAY_SECONDS
47
+ end
48
+
49
+ def to_s
50
+ super << '-day'
30
51
  end
31
-
32
- Chronic::Span.new(day_begin, day_end)
33
- end
34
-
35
- def offset(span, amount, pointer)
36
- direction = pointer == :future ? 1 : -1
37
- span + direction * amount * DAY_SECONDS
38
- end
39
-
40
- def width
41
- DAY_SECONDS
42
- end
43
-
44
- def to_s
45
- super << '-day'
46
52
  end
47
53
  end