chronic-davispuh 0.10.2.v0.1da32066b3f46f2506b3471e39557497e34afa27

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.travis.yml +10 -0
  4. data/Gemfile +3 -0
  5. data/HISTORY.md +243 -0
  6. data/LICENSE +21 -0
  7. data/README.md +185 -0
  8. data/Rakefile +68 -0
  9. data/chronic.gemspec +27 -0
  10. data/lib/chronic.rb +122 -0
  11. data/lib/chronic/arrow.rb +270 -0
  12. data/lib/chronic/date.rb +272 -0
  13. data/lib/chronic/definition.rb +208 -0
  14. data/lib/chronic/dictionary.rb +36 -0
  15. data/lib/chronic/handler.rb +44 -0
  16. data/lib/chronic/handlers/anchor.rb +65 -0
  17. data/lib/chronic/handlers/arrow.rb +84 -0
  18. data/lib/chronic/handlers/date.rb +270 -0
  19. data/lib/chronic/handlers/date_time.rb +72 -0
  20. data/lib/chronic/handlers/general.rb +130 -0
  21. data/lib/chronic/handlers/narrow.rb +54 -0
  22. data/lib/chronic/handlers/time.rb +167 -0
  23. data/lib/chronic/handlers/time_zone.rb +50 -0
  24. data/lib/chronic/objects/anchor_object.rb +263 -0
  25. data/lib/chronic/objects/arrow_object.rb +27 -0
  26. data/lib/chronic/objects/date_object.rb +164 -0
  27. data/lib/chronic/objects/date_time_object.rb +64 -0
  28. data/lib/chronic/objects/handler_object.rb +81 -0
  29. data/lib/chronic/objects/narrow_object.rb +85 -0
  30. data/lib/chronic/objects/time_object.rb +96 -0
  31. data/lib/chronic/objects/time_zone_object.rb +27 -0
  32. data/lib/chronic/parser.rb +154 -0
  33. data/lib/chronic/span.rb +32 -0
  34. data/lib/chronic/tag.rb +84 -0
  35. data/lib/chronic/tags/day_name.rb +34 -0
  36. data/lib/chronic/tags/day_portion.rb +33 -0
  37. data/lib/chronic/tags/day_special.rb +30 -0
  38. data/lib/chronic/tags/grabber.rb +29 -0
  39. data/lib/chronic/tags/keyword.rb +63 -0
  40. data/lib/chronic/tags/month_name.rb +39 -0
  41. data/lib/chronic/tags/ordinal.rb +52 -0
  42. data/lib/chronic/tags/pointer.rb +28 -0
  43. data/lib/chronic/tags/rational.rb +35 -0
  44. data/lib/chronic/tags/scalar.rb +101 -0
  45. data/lib/chronic/tags/season_name.rb +31 -0
  46. data/lib/chronic/tags/separator.rb +130 -0
  47. data/lib/chronic/tags/sign.rb +35 -0
  48. data/lib/chronic/tags/time_special.rb +34 -0
  49. data/lib/chronic/tags/time_zone.rb +56 -0
  50. data/lib/chronic/tags/unit.rb +174 -0
  51. data/lib/chronic/time.rb +141 -0
  52. data/lib/chronic/time_zone.rb +80 -0
  53. data/lib/chronic/token.rb +61 -0
  54. data/lib/chronic/token_group.rb +271 -0
  55. data/lib/chronic/tokenizer.rb +42 -0
  56. data/lib/chronic/version.rb +3 -0
  57. data/test/helper.rb +12 -0
  58. data/test/test_chronic.rb +190 -0
  59. data/test/test_daylight_savings.rb +98 -0
  60. data/test/test_handler.rb +113 -0
  61. data/test/test_parsing.rb +1520 -0
  62. data/test/test_span.rb +23 -0
  63. data/test/test_token.rb +31 -0
  64. metadata +218 -0
@@ -0,0 +1,141 @@
1
+ module Chronic
2
+ class Time
3
+ DAY_HOURS = 24
4
+ HOUR_MINUTES = 60
5
+ HOUR_SECONDS = 3600 # 60 * 60
6
+ MINUTE_SECONDS = 60
7
+ SECOND_SECONDS = 1 # haha, awesome
8
+ SUBSECOND_SECONDS = 0.001
9
+ SPECIAL = {
10
+ :am => (0... 12), # 0am to 12pm
11
+ :pm => (12...24), # 12am to 0am
12
+ :morning => (6... 12), # 6am to 12pm
13
+ :noon => (12.. 12), # 12pm
14
+ :afternoon => (13...17), # 1pm to 5pm
15
+ :evening => (17...20), # 5pm to 8pm
16
+ :night => (20...24), # 8pm to 0am
17
+ :midnight => (24.. 24) # 0am
18
+ }
19
+
20
+ # Checks if given number could be hour
21
+ def self.could_be_hour?(hour, width = nil, hours12 = false)
22
+ hour >= 0 && hour <= (hours12 ? 12 : 24) && (width.nil? || width > 0)
23
+ end
24
+
25
+ # Checks if given number could be minute
26
+ def self.could_be_minute?(minute, width = nil)
27
+ minute >= 0 && minute <= HOUR_MINUTES && (width.nil? || width <= 2)
28
+ end
29
+
30
+ # Checks if given number could be second
31
+ def self.could_be_second?(second, width = nil)
32
+ second >= 0 && second <= MINUTE_SECONDS && (width.nil? || width <= 2)
33
+ end
34
+
35
+ # Checks if given number could be subsecond
36
+ def self.could_be_subsecond?(subsecond, width = nil)
37
+ subsecond >= 0 && subsecond <= 99999999 && (width.nil? || width > 0)
38
+ end
39
+
40
+ def self.add_second(minute, second, amount = 1)
41
+ second += amount
42
+ if second >= MINUTE_SECONDS or second < 0
43
+ minute += second / MINUTE_SECONDS
44
+ second = second % MINUTE_SECONDS
45
+ end
46
+ [minute, second]
47
+ end
48
+
49
+ def self.add_minute(hour, minute, amount = 1)
50
+ minute += amount
51
+ if minute >= HOUR_MINUTES or minute < 0
52
+ hour += minute / HOUR_MINUTES
53
+ minute = minute % HOUR_MINUTES
54
+ end
55
+ [hour, minute]
56
+ end
57
+
58
+ def self.add_hour(day, hour, amount = 1)
59
+ hour += amount
60
+ if hour >= DAY_HOURS or hour < 0
61
+ day += hour / DAY_HOURS
62
+ hour = hour % DAY_HOURS
63
+ end
64
+ [day, hour]
65
+ end
66
+
67
+ def self.normalize(day, hour, minute, second)
68
+ minute, second = add_second(minute, second, 0)
69
+ hour, minute = add_minute(hour, minute, 0)
70
+ day, hour = add_hour(day, hour, 0)
71
+ [day, hour, minute, second]
72
+ end
73
+
74
+ def self.split(time)
75
+ if time.is_a?(::Time) or time.is_a?(::DateTime)
76
+ [time.hour, time.min, time.sec, time.to_time.utc_offset]
77
+ else
78
+ [0, 0, 0, nil]
79
+ end
80
+ end
81
+ end
82
+
83
+ module TimeStructure
84
+ include Comparable
85
+ attr_accessor :hour
86
+ attr_accessor :minute
87
+ attr_accessor :second
88
+ attr_reader :subsecond
89
+ attr_reader :subsecond_size
90
+ attr_reader :precision
91
+ def update(time)
92
+ @hour = time.hour
93
+ @minute = time.min
94
+ @second = time.sec
95
+ self
96
+ end
97
+
98
+ def is_equal?(time)
99
+ @hour == time.hour &&
100
+ @minute == time.min &&
101
+ @second == time.sec
102
+ end
103
+
104
+ def <=> (time)
105
+ to_f <=> time.hour * Time::HOUR_SECONDS + time.min * Time::MINUTE_SECONDS + time.sec
106
+ end
107
+
108
+ def to_a
109
+ [@hour, @minute, @second]
110
+ end
111
+
112
+ def to_f
113
+ @hour * Time::HOUR_SECONDS + @minute * Time::MINUTE_SECONDS + @second
114
+ end
115
+
116
+ def get_end
117
+ [@hour, @minute, @second]
118
+ end
119
+
120
+ def to_span(date, timezone = nil)
121
+ span_start = Chronic.construct(date.year, date.month, date.day, @hour, @minute, @second, timezone)
122
+ end_hour, end_minute, end_second = get_end
123
+ span_end = Chronic.construct(date.year, date.month, date.day, end_hour, end_minute, end_second, timezone)
124
+ Span.new(span_start, span_end, true)
125
+ end
126
+ end
127
+
128
+ class TimeInfo
129
+ include TimeStructure
130
+ def initialize(now = nil)
131
+ if now
132
+ update(now)
133
+ else
134
+ @hour = 0
135
+ @minute = 0
136
+ @second = 0
137
+ end
138
+ end
139
+ end
140
+
141
+ end
@@ -0,0 +1,80 @@
1
+ module Chronic
2
+ class TimeZone
3
+
4
+ # normalize offset in seconds to offset as string +mm:ss or -mm:ss
5
+ def self.normalize_offset(offset = nil)
6
+ return offset if offset.is_a?(String)
7
+ offset = Chronic.time_class.now.to_time.utc_offset unless offset # get current system's UTC offset if offset is nil
8
+ sign = '+'
9
+ sign = '-' if offset < 0
10
+ hours = (offset.abs / Time::HOUR_SECONDS).to_i.to_s.rjust(2,'0')
11
+ minutes = (offset.abs % Time::HOUR_SECONDS).to_s.rjust(2,'0')
12
+ sign + hours + minutes
13
+ end
14
+
15
+ def self.abbreviation_offests(abbr, date = nil)
16
+ TimezoneParser::Abbreviation.getOffsets(abbr, date, date).first
17
+ end
18
+
19
+ def self.name_offsets(name, date = nil)
20
+ TimezoneParser::Timezone.getOffsets(name, date, date).first
21
+ end
22
+
23
+ def self.zone_offsets(zone)
24
+ TZInfo::Timezone.get(@zone).current_period.utc_offset
25
+ end
26
+
27
+ def self.is_valid_abbr?(abbr)
28
+ TimezoneParser::Abbreviation.isValid?(abbr)
29
+ end
30
+
31
+ def self.is_valid_name?(name)
32
+ TimezoneParser::Timezone.isValid?(name)
33
+ end
34
+
35
+ def self.is_valid_zone?(name)
36
+ false # TODO
37
+ end
38
+
39
+ def self.to_offset(hour, minute, sign = 1)
40
+ offset = hour * Time::HOUR_SECONDS + minute * Time::MINUTE_SECONDS
41
+ offset *= sign
42
+ offset
43
+ end
44
+
45
+ end
46
+
47
+ module TimeZoneStructure
48
+ attr_reader :offset
49
+ attr_reader :sign
50
+ attr_reader :tzhour
51
+ attr_reader :tzminute
52
+ attr_reader :name
53
+ attr_reader :abbr
54
+ attr_reader :zone
55
+
56
+ def to_offset(year, month = 1, day = 1, hour = 0, minute = 0, second = 0)
57
+ date = DateTime.new(year, month, day, hour, minute, second)
58
+ if @abbr
59
+ TimeZone::abbreviation_offests(@abbr, date)
60
+ elsif @name
61
+ TimeZone::name_offsets(@name, date)
62
+ elsif @zone
63
+ TimeZone::zone_offsets(@zone)
64
+ elsif @tzhour
65
+ sign = 1
66
+ sign = -1 if @sign and @sign.type == :minus
67
+ TimeZone::to_offset(@tzhour, @tzminute, sign)
68
+ else
69
+ @offset
70
+ end
71
+ end
72
+
73
+ def to_s
74
+ sign = @sign ? @sign.type.inspect : 'nil'
75
+ "sign #{sign}, tzhour #{@tzhour.inspect}, tzminute #{@tzminute.inspect}, offset #{@offset.inspect}, name #{@name.inspect}, abbr #{@abbr.inspect}, zone #{@zone.inspect}"
76
+ end
77
+
78
+ end
79
+
80
+ end
@@ -0,0 +1,61 @@
1
+ module Chronic
2
+ class Token
3
+
4
+ attr_accessor :word
5
+ attr_accessor :tags
6
+
7
+ attr_reader :text
8
+ attr_reader :position
9
+
10
+ def initialize(word, text = nil, position = 0)
11
+ @word = word
12
+ @tags = []
13
+ @text = text
14
+ @position = position
15
+ end
16
+
17
+ def ==(token)
18
+ token.word == @word.downcase
19
+ end
20
+
21
+ # Tag this token with the specified tag.
22
+ #
23
+ # new_tag - The new Tag object.
24
+ #
25
+ # Returns nothing.
26
+ def tag(new_tag)
27
+ @tags << new_tag if new_tag
28
+ end
29
+
30
+ # Remove all tags of the given class.
31
+ #
32
+ # tag_class - The tag Class to remove.
33
+ #
34
+ # Returns nothing.
35
+ def untag(tag_class)
36
+ @tags.delete_if { |m| m.kind_of? tag_class }
37
+ end
38
+
39
+ # Returns true if this token has any tags.
40
+ def tagged?
41
+ @tags.size > 0
42
+ end
43
+
44
+ # tag_class - The tag Class to search for.
45
+ #
46
+ # Returns The first Tag that matches the given class.
47
+ def get_tag(tag_class)
48
+ @tags.find { |m| m.kind_of? tag_class }
49
+ end
50
+
51
+ # Print this Token in a pretty way
52
+ def to_s
53
+ @word + '(' + @tags.join(', ') + ') '
54
+ end
55
+
56
+ def inspect
57
+ to_s
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1,271 @@
1
+ require 'chronic/objects/handler_object'
2
+ require 'chronic/objects/anchor_object'
3
+ require 'chronic/objects/arrow_object'
4
+ require 'chronic/objects/narrow_object'
5
+ require 'chronic/objects/date_object'
6
+ require 'chronic/objects/date_time_object'
7
+ require 'chronic/objects/time_object'
8
+ require 'chronic/objects/time_zone_object'
9
+
10
+ module Chronic
11
+ class TokenGroup
12
+
13
+ attr_reader :arrows
14
+ attr_reader :narrows
15
+ attr_reader :dates
16
+ attr_reader :times
17
+ attr_reader :timezones
18
+ def initialize(tokens, definitions, local_date, options)
19
+ @anchors = []
20
+ @arrows = []
21
+ @narrows = []
22
+ @datetime = []
23
+ @dates = []
24
+ @times = []
25
+ @timezones = []
26
+ @local_date = local_date
27
+ @options = options
28
+
29
+ date_definitions = definitions[:date] + definitions[:endian] + definitions[:short_date]
30
+
31
+ tokens.each_index do |i|
32
+
33
+ if @anchors.last.nil? or i > @anchors.last.end
34
+ anchor = AnchorObject.new(tokens, i, definitions[:anchor], local_date, options)
35
+ @anchors << anchor if anchor.width > 0
36
+ end
37
+ @anchors.sort_by! { |a| a.width }.reverse!
38
+
39
+ if @arrows.last.nil? or i > @arrows.last.end
40
+ arrow = ArrowObject.new(tokens, i, definitions[:arrow], local_date, options)
41
+ @arrows << arrow if arrow.width > 0
42
+ end
43
+
44
+ if @narrows.last.nil? or i > @narrows.last.end
45
+ narrow = NarrowObject.new(tokens, i, definitions[:narrow], local_date, options)
46
+ @narrows << narrow if narrow.width > 0
47
+ end
48
+
49
+ if @datetime.last.nil? or i > @datetime.last.end
50
+ date = DateTimeObject.new(tokens, i, definitions[:date_time], local_date, options)
51
+ @datetime << date if date.width > 0
52
+ end
53
+
54
+ if @dates.last.nil? or i > @dates.last.end
55
+ date = DateObject.new(tokens, i, date_definitions, local_date, options)
56
+ @dates << date if date.width > 0
57
+ end
58
+
59
+ if @times.last.nil? or i > @times.last.end or not tokens[@times.last.begin].get_tag(ScalarWide).nil?
60
+ time = TimeObject.new(tokens, i, definitions[:time], local_date, options)
61
+ @times << time if time.width > 0
62
+ end
63
+ @times.sort_by! { |a| a.width }.reverse!
64
+
65
+ if @timezones.last.nil? or i > @timezones.last.end
66
+ timezone = TimeZoneObject.new(tokens, i, definitions[:timezone], local_date, options)
67
+ @timezones << timezone if timezone.width > 0
68
+ end
69
+
70
+ end
71
+ end
72
+
73
+ def get_anchor
74
+ @anchors.find do |anchor|
75
+ anchor.is_valid?
76
+ end
77
+ end
78
+
79
+ def get_arrow(anchor = nil)
80
+ arrows = @arrows.select do |arrow|
81
+ (anchor.nil? or (not arrow.overlap?(anchor.range) or arrow.width > anchor.width)) and
82
+ arrow.is_valid?
83
+ end
84
+ Arrow.new(arrows, @options) unless arrows.empty?
85
+ end
86
+
87
+ def get_narrow(anchor = nil, arrow = nil)
88
+ @narrows.find do |narrow|
89
+ (anchor.nil? or (not narrow.overlap?(anchor.range) or narrow.width >= anchor.width)) and
90
+ (arrow.nil? or not narrow.overlap?(arrow.range) or narrow.width >= arrow.width) and
91
+ narrow.is_valid?
92
+ end
93
+ end
94
+
95
+ def get_datetime(anchor = nil, arrow = nil, narrow = nil)
96
+ @datetime.find do |datetime|
97
+ (anchor.nil? or not datetime.overlap?(anchor.range)) and
98
+ (arrow.nil? or not datetime.overlap?(arrow.range)) and
99
+ (narrow.nil? or not datetime.overlap?(narrow.range)) and
100
+ datetime.is_valid?
101
+ end
102
+ end
103
+
104
+ def get_date(anchor = nil, arrow = nil, narrow = nil, datetime = nil)
105
+ @dates.find do |date|
106
+ (anchor.nil? or not date.overlap?(anchor.range)) and
107
+ (arrow.nil? or (not date.overlap?(arrow.range) or date.width > arrow.width or narrow)) and
108
+ (narrow.nil? or not date.overlap?(narrow.range)) and
109
+ (datetime.nil? or not date.overlap?(datetime.range)) and
110
+ date.is_valid?
111
+ end
112
+ end
113
+
114
+ def get_next_date(anchor = nil, arrow, narrow, datetime, date, time, timezone)
115
+ @dates.find do |nextdate|
116
+ not nextdate.overlap?(date.range) and
117
+ (anchor.nil? or not nextdate.overlap?(anchor.range)) and
118
+ (arrow.nil? or not nextdate.overlap?(arrow.range)) and
119
+ (narrow.nil? or not nextdate.overlap?(narrow.range)) and
120
+ (datetime.nil? or not nextdate.overlap?(datetime.range)) and
121
+ (time.nil? or not nextdate.overlap?(time.range)) and
122
+ (timezone.nil? or not nextdate.overlap?(timezone.range)) and
123
+ nextdate.is_valid? and not nextdate.year.nil?
124
+ end
125
+ end
126
+
127
+ def get_time(anchor = nil, arrow = nil, narrow = nil, datetime = nil, date = nil)
128
+ @times.find do |time|
129
+ (anchor.nil? or (not time.overlap?(anchor.range) or time.width > anchor.width)) and
130
+ (arrow.nil? or (not time.overlap?(arrow.range) or time.end >= arrow.end)) and
131
+ (narrow.nil? or not time.overlap?(narrow.range)) and
132
+ (datetime.nil? or not time.overlap?(datetime.range)) and
133
+ (date.nil? or (not time.overlap?(date.range) or time.width >= date.width )) and
134
+ time.is_valid?
135
+ end
136
+ end
137
+
138
+ def get_timezone(anchor = nil, arrow = nil, narrow = nil, datetime = nil, date = nil, time = nil)
139
+ @timezones.find do |timezone|
140
+ (anchor.nil? or not timezone.overlap?(anchor.range)) and
141
+ (arrow.nil? or not timezone.overlap?(arrow.range)) and
142
+ (narrow.nil? or not timezone.overlap?(narrow.range)) and
143
+ (datetime.nil? or not timezone.overlap?(datetime.range)) and
144
+ (date.nil? or not timezone.overlap?(date.range)) and
145
+ (time.nil? or not timezone.overlap?(time.range)) and
146
+ timezone.is_valid?
147
+ end
148
+ end
149
+
150
+ def update_date(anchor, arrow, narrow, datetime, date, time, timezone)
151
+ return if not date or date.year.nil?
152
+ next_date = get_next_date(anchor, arrow, narrow, datetime, date, time, timezone)
153
+ date.year = next_date.year if next_date
154
+ end
155
+
156
+ def refresh(anchor, arrow, narrow, datetime, date, time, timezone)
157
+ anchor = nil if anchor and (
158
+ (arrow and anchor.overlap?(arrow.range)) or
159
+ (datetime and anchor.overlap?(datetime.range)) or
160
+ (date and anchor.overlap?(date.range)) or
161
+ (time and anchor.overlap?(time.range)) or
162
+ (timezone and anchor.overlap?(timezone.range))
163
+ )
164
+ arrow = nil if arrow and (
165
+ (narrow and arrow.overlap?(narrow.range)) or
166
+ (datetime and arrow.overlap?(datetime.range)) or
167
+ (date and arrow.overlap?(date.range)) or
168
+ (time and arrow.overlap?(time.range)) or
169
+ (timezone and arrow.overlap?(timezone.range))
170
+ )
171
+ narrow = nil if narrow and (
172
+ (datetime and narrow.overlap?(datetime.range)) or
173
+ (date and narrow.overlap?(date.range)) or
174
+ (time and narrow.overlap?(time.range)) or
175
+ (timezone and narrow.overlap?(timezone.range))
176
+ )
177
+
178
+ if anchor and narrow and anchor.overlap?(narrow.range)
179
+ if date or narrow.width > anchor.width
180
+ anchor = nil
181
+ else
182
+ narrow = nil
183
+ end
184
+ end
185
+
186
+ if date and time and date.overlap?(time.range)
187
+ if time.width > date.width or anchor
188
+ date = nil
189
+ else
190
+ time = nil
191
+ end
192
+ end
193
+ [anchor, arrow, narrow, datetime, date, time, timezone]
194
+ end
195
+
196
+ def get_all
197
+ anchor = get_anchor
198
+ arrow = get_arrow(anchor)
199
+ narrow = get_narrow(anchor, arrow)
200
+ datetime = get_datetime(anchor, arrow, narrow)
201
+ date = get_date(anchor, arrow, narrow, datetime)
202
+ time = get_time(anchor, arrow, narrow, datetime, date)
203
+ timezone = get_timezone(anchor, arrow, narrow, datetime, date, time)
204
+ update_date(anchor, arrow, narrow, datetime, date, time, timezone)
205
+ refresh(anchor, arrow, narrow, datetime, date, time, timezone)
206
+ end
207
+
208
+ def get_sign
209
+ (@options[:context] == :past) ? -1 : ((@options[:context] == :future) ? 1 : 0)
210
+ end
211
+
212
+ def to_span
213
+ span = nil
214
+ objects = get_all
215
+ anchor, arrow, narrow, datetime, date, time, timezone = objects
216
+ if datetime
217
+ puts "\nUse " + datetime.class.to_s if Chronic.debug
218
+ span = datetime.to_span
219
+ elsif anchor or arrow or narrow or datetime or date or time
220
+ puts "\nUse " + objects.reject(&:nil?).sort_by { |o| o.begin }.map(&:class).join(' + ') if Chronic.debug
221
+
222
+ if arrow
223
+ time = TimeInfo.new(@local_date) if not time
224
+ arrow_date = date
225
+ arrow_date = DateInfo.new(@local_date) unless arrow_date
226
+ span = arrow_date.to_span(time, timezone)
227
+ span = arrow.to_span(span, timezone)
228
+ end
229
+
230
+ if anchor
231
+ time = TimeInfo.new(@local_date) if not time
232
+ span = anchor.to_span(span, time, timezone)
233
+ if date
234
+ sbegin = span.begin
235
+ date.local_date = sbegin
236
+ date.force_normalize!
237
+ span = date.to_span(nil, timezone)
238
+ sign = get_sign
239
+ if not sign.zero? and date.wday.nil? and (span.begin - @local_date) * sign < 0
240
+ year, month, day = Date::split(sbegin)
241
+ date.local_date = ::Time::mktime(year + sign, month, day)
242
+ date.force_normalize!
243
+ span = date.to_span(nil, timezone)
244
+ end
245
+ end
246
+ end
247
+
248
+ if not arrow and not anchor and time
249
+ sign = get_sign
250
+ time_compare = sign.zero? ? false : ((sign == -1) ? (time > @local_date) : (time < @local_date))
251
+ date = DateInfo.new(@local_date) unless date
252
+ date.add_day(sign) if not date.is_a?(DateObject) and date.is_equal?(@local_date) and time_compare
253
+ span = time.to_span(date, timezone)
254
+ end
255
+
256
+ span = date.to_span(nil, timezone) if span.nil? and date
257
+
258
+ span = narrow.to_span(span, timezone) if narrow
259
+
260
+ end
261
+
262
+ if Chronic.debug
263
+ puts "\n-- Span" + span.to_s if span
264
+ puts '-none' unless span
265
+ end
266
+
267
+ span
268
+ end
269
+
270
+ end
271
+ end