chronic-davispuh 0.10.2.v0.1da32066b3f46f2506b3471e39557497e34afa27
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +10 -0
- data/Gemfile +3 -0
- data/HISTORY.md +243 -0
- data/LICENSE +21 -0
- data/README.md +185 -0
- data/Rakefile +68 -0
- data/chronic.gemspec +27 -0
- data/lib/chronic.rb +122 -0
- data/lib/chronic/arrow.rb +270 -0
- data/lib/chronic/date.rb +272 -0
- data/lib/chronic/definition.rb +208 -0
- data/lib/chronic/dictionary.rb +36 -0
- data/lib/chronic/handler.rb +44 -0
- data/lib/chronic/handlers/anchor.rb +65 -0
- data/lib/chronic/handlers/arrow.rb +84 -0
- data/lib/chronic/handlers/date.rb +270 -0
- data/lib/chronic/handlers/date_time.rb +72 -0
- data/lib/chronic/handlers/general.rb +130 -0
- data/lib/chronic/handlers/narrow.rb +54 -0
- data/lib/chronic/handlers/time.rb +167 -0
- data/lib/chronic/handlers/time_zone.rb +50 -0
- data/lib/chronic/objects/anchor_object.rb +263 -0
- data/lib/chronic/objects/arrow_object.rb +27 -0
- data/lib/chronic/objects/date_object.rb +164 -0
- data/lib/chronic/objects/date_time_object.rb +64 -0
- data/lib/chronic/objects/handler_object.rb +81 -0
- data/lib/chronic/objects/narrow_object.rb +85 -0
- data/lib/chronic/objects/time_object.rb +96 -0
- data/lib/chronic/objects/time_zone_object.rb +27 -0
- data/lib/chronic/parser.rb +154 -0
- data/lib/chronic/span.rb +32 -0
- data/lib/chronic/tag.rb +84 -0
- data/lib/chronic/tags/day_name.rb +34 -0
- data/lib/chronic/tags/day_portion.rb +33 -0
- data/lib/chronic/tags/day_special.rb +30 -0
- data/lib/chronic/tags/grabber.rb +29 -0
- data/lib/chronic/tags/keyword.rb +63 -0
- data/lib/chronic/tags/month_name.rb +39 -0
- data/lib/chronic/tags/ordinal.rb +52 -0
- data/lib/chronic/tags/pointer.rb +28 -0
- data/lib/chronic/tags/rational.rb +35 -0
- data/lib/chronic/tags/scalar.rb +101 -0
- data/lib/chronic/tags/season_name.rb +31 -0
- data/lib/chronic/tags/separator.rb +130 -0
- data/lib/chronic/tags/sign.rb +35 -0
- data/lib/chronic/tags/time_special.rb +34 -0
- data/lib/chronic/tags/time_zone.rb +56 -0
- data/lib/chronic/tags/unit.rb +174 -0
- data/lib/chronic/time.rb +141 -0
- data/lib/chronic/time_zone.rb +80 -0
- data/lib/chronic/token.rb +61 -0
- data/lib/chronic/token_group.rb +271 -0
- data/lib/chronic/tokenizer.rb +42 -0
- data/lib/chronic/version.rb +3 -0
- data/test/helper.rb +12 -0
- data/test/test_chronic.rb +190 -0
- data/test/test_daylight_savings.rb +98 -0
- data/test/test_handler.rb +113 -0
- data/test/test_parsing.rb +1520 -0
- data/test/test_span.rb +23 -0
- data/test/test_token.rb +31 -0
- metadata +218 -0
data/lib/chronic/time.rb
ADDED
@@ -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
|