chronic 0.3.0 → 0.4.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.
- data/HISTORY.md +27 -0
- data/Manifest.txt +16 -5
- data/README.md +14 -8
- data/Rakefile +2 -8
- data/chronic.gemspec +8 -11
- data/lib/chronic.rb +21 -14
- data/lib/chronic/chronic.rb +38 -130
- data/lib/chronic/grabber.rb +11 -15
- data/lib/chronic/handlers.rb +63 -40
- data/lib/chronic/mini_date.rb +27 -0
- data/lib/chronic/numerizer.rb +120 -0
- data/lib/chronic/ordinal.rb +5 -10
- data/lib/chronic/pointer.rb +8 -10
- data/lib/chronic/repeater.rb +106 -109
- data/lib/chronic/repeaters/repeater_day.rb +43 -41
- data/lib/chronic/repeaters/repeater_day_name.rb +38 -36
- data/lib/chronic/repeaters/repeater_day_portion.rb +74 -73
- data/lib/chronic/repeaters/repeater_fortnight.rb +57 -55
- data/lib/chronic/repeaters/repeater_hour.rb +46 -44
- data/lib/chronic/repeaters/repeater_minute.rb +46 -44
- data/lib/chronic/repeaters/repeater_month.rb +52 -50
- data/lib/chronic/repeaters/repeater_month_name.rb +84 -80
- data/lib/chronic/repeaters/repeater_season.rb +97 -119
- data/lib/chronic/repeaters/repeater_season_name.rb +39 -39
- data/lib/chronic/repeaters/repeater_second.rb +32 -30
- data/lib/chronic/repeaters/repeater_time.rb +106 -101
- data/lib/chronic/repeaters/repeater_week.rb +60 -58
- data/lib/chronic/repeaters/repeater_weekday.rb +67 -58
- data/lib/chronic/repeaters/repeater_weekend.rb +54 -52
- data/lib/chronic/repeaters/repeater_year.rb +50 -48
- data/lib/chronic/scalar.rb +24 -16
- data/lib/chronic/separator.rb +15 -33
- data/lib/chronic/span.rb +31 -0
- data/lib/chronic/tag.rb +26 -0
- data/lib/chronic/time_zone.rb +7 -9
- data/lib/chronic/token.rb +35 -0
- data/test/helper.rb +5 -6
- data/test/test_Chronic.rb +5 -0
- data/test/test_Numerizer.rb +60 -39
- data/test/test_RepeaterHour.rb +4 -0
- data/test/test_parsing.rb +104 -13
- metadata +14 -20
- data/lib/chronic/numerizer/numerizer.rb +0 -97
data/HISTORY.md
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
# 0.4.0 / 2011-06-04
|
2
|
+
|
3
|
+
* Ensure context is being passed through grabbers. Now "Sunday at 2:18pm"
|
4
|
+
with `:context => :past` will return the correct date
|
5
|
+
* Support parsing ordinal strings (eg first, twenty third => 1st, 23rd)
|
6
|
+
* Seasons now ignore DST and return 00 as an hour
|
7
|
+
* Support parsing 2 digit years and added `ambiguous_year_future_bias` option
|
8
|
+
* Support parsing 'thurs' for Thursday
|
9
|
+
* Fix pre_normalize() to remove periods before numerizing
|
10
|
+
* Fix RepeaterDays to not add an extra hour in future tense. This meant
|
11
|
+
when parsing 'yesterday' after 11PM, Chronic would return today
|
12
|
+
* Discard any prefixed 0 for time strings when using post noon portion
|
13
|
+
* Gemspec updates for RubyGems deprecations
|
14
|
+
* Ensure 0:10 is treated like 00:10
|
15
|
+
* Ensure we load classes after setting Chronic class instance variables
|
16
|
+
so we can debug initialization and do assignments at compile time
|
17
|
+
* Added a Tag.scan_for method for DRYing up some scanning code
|
18
|
+
* Move some classes into their own files for maintainability
|
19
|
+
* Numerizer.andition should be a private class method, make it so
|
20
|
+
* Namespaced Numerizer, Season and MiniDate (Sascha Teske)
|
21
|
+
* Support for Ruby 1.9 (Dave Lee, Aaron Hurley)
|
22
|
+
* Fix `:context => :past` where parsed date is in current month (Marc Hedlund)
|
23
|
+
* Fix undefined variable in RepeaterHour (Ryan Garver)
|
24
|
+
* Added support for parsing 'Fourty' as another mis-spelling (Lee Reilly)
|
25
|
+
* Added ordinal format support: ie 'February 14th, 2004' (Jeff Felchner)
|
26
|
+
* Fix dates when working with daylight saving times Mike Mangino
|
27
|
+
|
1
28
|
# 0.3.0 / 2010-10-22
|
2
29
|
|
3
30
|
* Fix numerizer number combination bug (27 Oct 2006 7:30pm works now)
|
data/Manifest.txt
CHANGED
@@ -1,11 +1,16 @@
|
|
1
|
-
|
1
|
+
HISTORY.md
|
2
|
+
LICENSE
|
2
3
|
Manifest.txt
|
3
|
-
README.
|
4
|
+
README.md
|
4
5
|
Rakefile
|
6
|
+
benchmark/benchmark.rb
|
7
|
+
chronic.gemspec
|
5
8
|
lib/chronic.rb
|
6
9
|
lib/chronic/chronic.rb
|
7
10
|
lib/chronic/grabber.rb
|
8
11
|
lib/chronic/handlers.rb
|
12
|
+
lib/chronic/mini_date.rb
|
13
|
+
lib/chronic/numerizer.rb
|
9
14
|
lib/chronic/ordinal.rb
|
10
15
|
lib/chronic/pointer.rb
|
11
16
|
lib/chronic/repeater.rb
|
@@ -22,26 +27,32 @@ lib/chronic/repeaters/repeater_season_name.rb
|
|
22
27
|
lib/chronic/repeaters/repeater_second.rb
|
23
28
|
lib/chronic/repeaters/repeater_time.rb
|
24
29
|
lib/chronic/repeaters/repeater_week.rb
|
30
|
+
lib/chronic/repeaters/repeater_weekday.rb
|
25
31
|
lib/chronic/repeaters/repeater_weekend.rb
|
26
32
|
lib/chronic/repeaters/repeater_year.rb
|
27
33
|
lib/chronic/scalar.rb
|
28
34
|
lib/chronic/separator.rb
|
35
|
+
lib/chronic/span.rb
|
36
|
+
lib/chronic/tag.rb
|
29
37
|
lib/chronic/time_zone.rb
|
30
|
-
lib/
|
31
|
-
test/
|
38
|
+
lib/chronic/token.rb
|
39
|
+
test/helper.rb
|
32
40
|
test/test_Chronic.rb
|
41
|
+
test/test_DaylightSavings.rb
|
33
42
|
test/test_Handler.rb
|
34
43
|
test/test_Numerizer.rb
|
35
44
|
test/test_RepeaterDayName.rb
|
36
45
|
test/test_RepeaterFortnight.rb
|
37
46
|
test/test_RepeaterHour.rb
|
47
|
+
test/test_RepeaterMinute.rb
|
38
48
|
test/test_RepeaterMonth.rb
|
39
49
|
test/test_RepeaterMonthName.rb
|
40
50
|
test/test_RepeaterTime.rb
|
41
51
|
test/test_RepeaterWeek.rb
|
52
|
+
test/test_RepeaterWeekday.rb
|
42
53
|
test/test_RepeaterWeekend.rb
|
43
54
|
test/test_RepeaterYear.rb
|
44
55
|
test/test_Span.rb
|
45
56
|
test/test_Time.rb
|
46
57
|
test/test_Token.rb
|
47
|
-
test/test_parsing.rb
|
58
|
+
test/test_parsing.rb
|
data/README.md
CHANGED
@@ -9,23 +9,26 @@ for the wide variety of formats Chronic will parse.
|
|
9
9
|
|
10
10
|
## INSTALLATION
|
11
11
|
|
12
|
-
|
12
|
+
### RubyGems
|
13
13
|
|
14
14
|
$ [sudo] gem install chronic
|
15
15
|
|
16
|
+
### GitHub
|
17
|
+
|
18
|
+
$ git clone git://github.com/mojombo/chronic.git
|
19
|
+
$ cd chronic && gem build chronic.gemspec
|
20
|
+
$ gem install chronic-<version>.gem
|
21
|
+
|
16
22
|
|
17
23
|
## USAGE
|
18
24
|
|
19
25
|
You can parse strings containing a natural language date using the
|
20
|
-
Chronic.parse method.
|
26
|
+
`Chronic.parse` method.
|
21
27
|
|
22
|
-
require 'rubygems'
|
23
28
|
require 'chronic'
|
24
29
|
|
25
30
|
Time.now #=> Sun Aug 27 23:18:25 PDT 2006
|
26
31
|
|
27
|
-
#---
|
28
|
-
|
29
32
|
Chronic.parse('tomorrow')
|
30
33
|
#=> Mon Aug 28 12:00:00 PDT 2006
|
31
34
|
|
@@ -44,7 +47,7 @@ Chronic.parse method.
|
|
44
47
|
Chronic.parse('may 27th', :guess => false)
|
45
48
|
#=> Sun May 27 00:00:00 PDT 2007..Mon May 28 00:00:00 PDT 2007
|
46
49
|
|
47
|
-
See Chronic.parse for detailed usage instructions.
|
50
|
+
See `Chronic.parse` for detailed usage instructions.
|
48
51
|
|
49
52
|
|
50
53
|
## EXAMPLES
|
@@ -99,12 +102,14 @@ Complex
|
|
99
102
|
Specific Dates
|
100
103
|
|
101
104
|
* January 5
|
105
|
+
* February twenty first
|
102
106
|
* dec 25
|
103
107
|
* may 27th
|
104
108
|
* October 2006
|
105
109
|
* oct 06
|
106
110
|
* jan 3 2010
|
107
111
|
* february 14, 2004
|
112
|
+
* february 14th, 2004
|
108
113
|
* 3 jan 2000
|
109
114
|
* 17 april 85
|
110
115
|
* 5/27/1979
|
@@ -149,7 +154,7 @@ Support for a wider range of times is planned for a future release.
|
|
149
154
|
|
150
155
|
If you'd like to hack on Chronic, start by forking the repo on GitHub:
|
151
156
|
|
152
|
-
|
157
|
+
https://github.com/mojombo/chronic
|
153
158
|
|
154
159
|
To get all of the dependencies, install the gem first. The best way to get
|
155
160
|
your changes merged back into core is as follows:
|
@@ -158,8 +163,9 @@ your changes merged back into core is as follows:
|
|
158
163
|
1. Create a thoughtfully named topic branch to contain your change
|
159
164
|
1. Hack away
|
160
165
|
1. Add tests and make sure everything still passes by running `rake`
|
166
|
+
1. Ensure your tests pass in multiple timezones
|
161
167
|
1. If you are adding new functionality, document it in the README
|
162
168
|
1. Do not change the version number, we will do that on our end
|
163
169
|
1. If necessary, rebase your commits into logical chunks, without errors
|
164
170
|
1. Push the branch up to GitHub
|
165
|
-
1. Send a pull request for your branch
|
171
|
+
1. Send a pull request for your branch
|
data/Rakefile
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'rake'
|
3
1
|
require 'date'
|
4
2
|
|
5
3
|
#############################################################################
|
@@ -17,10 +15,6 @@ def version
|
|
17
15
|
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
18
16
|
end
|
19
17
|
|
20
|
-
def date
|
21
|
-
Date.today.to_s
|
22
|
-
end
|
23
|
-
|
24
18
|
def rubyforge_project
|
25
19
|
name
|
26
20
|
end
|
@@ -70,7 +64,7 @@ end
|
|
70
64
|
|
71
65
|
desc "Open an irb session preloaded with this library"
|
72
66
|
task :console do
|
73
|
-
sh "irb -
|
67
|
+
sh "irb -Ilib -rchronic"
|
74
68
|
end
|
75
69
|
|
76
70
|
#############################################################################
|
@@ -113,7 +107,7 @@ task :gemspec => :validate do
|
|
113
107
|
# replace name version and date
|
114
108
|
replace_header(head, :name)
|
115
109
|
replace_header(head, :version)
|
116
|
-
|
110
|
+
|
117
111
|
#comment this out if your rubyforge_project has a different name
|
118
112
|
replace_header(head, :rubyforge_project)
|
119
113
|
|
data/chronic.gemspec
CHANGED
@@ -1,22 +1,15 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
|
-
s.specification_version = 2 if s.respond_to? :specification_version=
|
3
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
|
-
s.rubygems_version = '1.3.5'
|
5
|
-
|
6
2
|
s.name = 'chronic'
|
7
|
-
s.version = '0.
|
8
|
-
s.date = '2010-10-22'
|
3
|
+
s.version = '0.4.0'
|
9
4
|
s.rubyforge_project = 'chronic'
|
10
5
|
|
11
6
|
s.summary = "Natural language date/time parsing."
|
12
7
|
s.description = "Chronic is a natural language date/time parser written in pure Ruby."
|
13
8
|
|
14
|
-
s.authors = ["Tom Preston-Werner"]
|
15
|
-
s.email = 'tom@mojombo.com'
|
9
|
+
s.authors = ["Tom Preston-Werner", "Lee Jarvis"]
|
10
|
+
s.email = ['tom@mojombo.com', 'lee@jarvis.co']
|
16
11
|
s.homepage = 'http://github.com/mojombo/chronic'
|
17
12
|
|
18
|
-
s.require_paths = %w[lib]
|
19
|
-
|
20
13
|
s.rdoc_options = ["--charset=UTF-8"]
|
21
14
|
s.extra_rdoc_files = %w[README.md HISTORY.md LICENSE]
|
22
15
|
|
@@ -33,7 +26,8 @@ Gem::Specification.new do |s|
|
|
33
26
|
lib/chronic/chronic.rb
|
34
27
|
lib/chronic/grabber.rb
|
35
28
|
lib/chronic/handlers.rb
|
36
|
-
lib/chronic/
|
29
|
+
lib/chronic/mini_date.rb
|
30
|
+
lib/chronic/numerizer.rb
|
37
31
|
lib/chronic/ordinal.rb
|
38
32
|
lib/chronic/pointer.rb
|
39
33
|
lib/chronic/repeater.rb
|
@@ -55,7 +49,10 @@ Gem::Specification.new do |s|
|
|
55
49
|
lib/chronic/repeaters/repeater_year.rb
|
56
50
|
lib/chronic/scalar.rb
|
57
51
|
lib/chronic/separator.rb
|
52
|
+
lib/chronic/span.rb
|
53
|
+
lib/chronic/tag.rb
|
58
54
|
lib/chronic/time_zone.rb
|
55
|
+
lib/chronic/token.rb
|
59
56
|
test/helper.rb
|
60
57
|
test/test_Chronic.rb
|
61
58
|
test/test_DaylightSavings.rb
|
data/lib/chronic.rb
CHANGED
@@ -7,12 +7,27 @@
|
|
7
7
|
#
|
8
8
|
#=============================================================================
|
9
9
|
|
10
|
-
|
10
|
+
module Chronic
|
11
|
+
VERSION = "0.4.0"
|
12
|
+
|
13
|
+
class << self
|
14
|
+
attr_accessor :debug
|
15
|
+
attr_accessor :time_class
|
16
|
+
end
|
17
|
+
|
18
|
+
self.debug = false
|
19
|
+
self.time_class = Time
|
20
|
+
end
|
11
21
|
|
12
22
|
require 'time'
|
23
|
+
require 'date'
|
13
24
|
|
14
25
|
require 'chronic/chronic'
|
15
26
|
require 'chronic/handlers'
|
27
|
+
require 'chronic/mini_date'
|
28
|
+
require 'chronic/tag'
|
29
|
+
require 'chronic/span'
|
30
|
+
require 'chronic/token'
|
16
31
|
|
17
32
|
require 'chronic/repeater'
|
18
33
|
require 'chronic/repeaters/repeater_year'
|
@@ -39,19 +54,7 @@ require 'chronic/ordinal'
|
|
39
54
|
require 'chronic/separator'
|
40
55
|
require 'chronic/time_zone'
|
41
56
|
|
42
|
-
require 'chronic/numerizer
|
43
|
-
|
44
|
-
module Chronic
|
45
|
-
VERSION = "0.3.0"
|
46
|
-
|
47
|
-
class << self
|
48
|
-
attr_accessor :debug
|
49
|
-
attr_accessor :time_class
|
50
|
-
end
|
51
|
-
|
52
|
-
self.debug = false
|
53
|
-
self.time_class = Time
|
54
|
-
end
|
57
|
+
require 'chronic/numerizer'
|
55
58
|
|
56
59
|
# class Time
|
57
60
|
# def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0)
|
@@ -124,4 +127,8 @@ class Time
|
|
124
127
|
|
125
128
|
Chronic.time_class.local(year, month, day, hour, minute, second)
|
126
129
|
end
|
130
|
+
|
131
|
+
def to_minidate
|
132
|
+
Chronic::MiniDate.new(self.month, self.day)
|
133
|
+
end
|
127
134
|
end
|
data/lib/chronic/chronic.rb
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
module Chronic
|
2
|
+
|
3
|
+
DEFAULT_OPTIONS = {
|
4
|
+
:context => :future,
|
5
|
+
:now => nil,
|
6
|
+
:guess => true,
|
7
|
+
:ambiguous_time_range => 6,
|
8
|
+
:endian_precedence => [:middle, :little],
|
9
|
+
:ambiguous_year_future_bias => 50
|
10
|
+
}
|
11
|
+
|
2
12
|
class << self
|
3
13
|
|
4
14
|
# Parses a string containing a natural language date or time. If the parser
|
@@ -38,48 +48,31 @@ module Chronic
|
|
38
48
|
# assume that means 5:00pm. If <tt>:none</tt> is given, no assumption
|
39
49
|
# will be made, and the first matching instance of that time will
|
40
50
|
# be used.
|
51
|
+
#
|
52
|
+
# [<tt>:endian_precedence</tt>]
|
53
|
+
# Array (defaults to <tt>[:middle, :little]</tt>)
|
54
|
+
#
|
55
|
+
# By default, Chronic will parse "03/04/2011" as the fourth day
|
56
|
+
# of the third month. Alternatively you can tell Chronic to parse
|
57
|
+
# this as the third day of the fourth month by altering the
|
58
|
+
# <tt>:endian_precedence</tt> to <tt>[:little, :middle]</tt>.
|
41
59
|
def parse(text, specified_options = {})
|
42
60
|
@text = text
|
43
|
-
|
44
|
-
# get options and set defaults if necessary
|
45
|
-
default_options = {:context => :future,
|
46
|
-
:now => Chronic.time_class.now,
|
47
|
-
:guess => true,
|
48
|
-
:ambiguous_time_range => 6,
|
49
|
-
:endian_precedence => nil}
|
50
|
-
options = default_options.merge specified_options
|
51
|
-
|
52
|
-
# handle options that were set to nil
|
53
|
-
options[:context] = :future unless options[:context]
|
54
|
-
options[:now] = Chronic.time_class.now unless options[:context]
|
55
|
-
options[:ambiguous_time_range] = 6 unless options[:ambiguous_time_range]
|
61
|
+
options = DEFAULT_OPTIONS.merge specified_options
|
56
62
|
|
57
63
|
# ensure the specified options are valid
|
58
|
-
specified_options.keys.each
|
59
|
-
|
60
|
-
end
|
64
|
+
(specified_options.keys-DEFAULT_OPTIONS.keys).each {|key| raise(InvalidArgumentException, "#{key} is not a valid option key.")}
|
65
|
+
|
61
66
|
[:past, :future, :none].include?(options[:context]) || raise(InvalidArgumentException, "Invalid value ':#{options[:context]}' for :context specified. Valid values are :past and :future.")
|
62
67
|
|
63
|
-
|
68
|
+
options[:now] ||= Chronic.time_class.now
|
64
69
|
@now = options[:now]
|
65
70
|
|
66
71
|
# put the text into a normal format to ease scanning
|
67
|
-
text =
|
68
|
-
|
69
|
-
# get base tokens for each word
|
70
|
-
@tokens = self.base_tokenize(text)
|
71
|
-
|
72
|
-
# scan the tokens with each token scanner
|
73
|
-
[Repeater].each do |tokenizer|
|
74
|
-
@tokens = tokenizer.scan(@tokens, options)
|
75
|
-
end
|
76
|
-
|
77
|
-
[Grabber, Pointer, Scalar, Ordinal, Separator, TimeZone].each do |tokenizer|
|
78
|
-
@tokens = tokenizer.scan(@tokens)
|
79
|
-
end
|
72
|
+
text = pre_normalize(text)
|
80
73
|
|
81
|
-
#
|
82
|
-
@tokens =
|
74
|
+
# tokenize words
|
75
|
+
@tokens = tokenize(text, options)
|
83
76
|
|
84
77
|
if Chronic.debug
|
85
78
|
puts "+---------------------------------------------------"
|
@@ -87,19 +80,12 @@ module Chronic
|
|
87
80
|
puts "+---------------------------------------------------"
|
88
81
|
end
|
89
82
|
|
90
|
-
|
91
|
-
begin
|
92
|
-
span = self.tokens_to_span(@tokens, options)
|
93
|
-
rescue
|
94
|
-
raise
|
95
|
-
return nil
|
96
|
-
end
|
83
|
+
span = tokens_to_span(@tokens, options)
|
97
84
|
|
98
|
-
# guess a time within a span if required
|
99
85
|
if options[:guess]
|
100
|
-
|
86
|
+
guess span
|
101
87
|
else
|
102
|
-
|
88
|
+
span
|
103
89
|
end
|
104
90
|
end
|
105
91
|
|
@@ -109,10 +95,12 @@ module Chronic
|
|
109
95
|
# ordinals (third => 3rd)
|
110
96
|
def pre_normalize(text) #:nodoc:
|
111
97
|
normalized_text = text.to_s.downcase
|
112
|
-
normalized_text = numericize_numbers(normalized_text)
|
113
98
|
normalized_text.gsub!(/['"\.,]/, '')
|
99
|
+
normalized_text.gsub!(/\bsecond (of|day|month|hour|minute|second)\b/, '2nd \1')
|
100
|
+
normalized_text = numericize_numbers(normalized_text)
|
114
101
|
normalized_text.gsub!(/ \-(\d{4})\b/, ' tzminus\1')
|
115
102
|
normalized_text.gsub!(/([\/\-\,\@])/) { ' ' + $1 + ' ' }
|
103
|
+
normalized_text.gsub!(/\b0(\d+:\d+\s*pm?\b)/, '\1')
|
116
104
|
normalized_text.gsub!(/\btoday\b/, 'this day')
|
117
105
|
normalized_text.gsub!(/\btomm?orr?ow\b/, 'next day')
|
118
106
|
normalized_text.gsub!(/\byesterday\b/, 'last day')
|
@@ -129,7 +117,7 @@ module Chronic
|
|
129
117
|
normalized_text.gsub!(/\b\d+:?\d*[ap]\b/,'\0m')
|
130
118
|
normalized_text.gsub!(/(\d)([ap]m|oclock)\b/, '\1 \2')
|
131
119
|
normalized_text.gsub!(/\b(hence|after|from)\b/, 'future')
|
132
|
-
normalized_text
|
120
|
+
normalized_text
|
133
121
|
end
|
134
122
|
|
135
123
|
# Convert number words to numbers (three => 3)
|
@@ -137,15 +125,12 @@ module Chronic
|
|
137
125
|
Numerizer.numerize(text)
|
138
126
|
end
|
139
127
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
# a Token
|
147
|
-
def base_tokenize(text) #:nodoc:
|
148
|
-
text.split(' ').map { |word| Token.new(word) }
|
128
|
+
def tokenize(text, options) #:nodoc:
|
129
|
+
tokens = text.split(' ').map { |word| Token.new(word) }
|
130
|
+
[Repeater, Grabber, Pointer, Scalar, Ordinal, Separator, TimeZone].each do |tok|
|
131
|
+
tokens = tok.scan(tokens, options)
|
132
|
+
end
|
133
|
+
tokens.delete_if { |token| !token.tagged? }
|
149
134
|
end
|
150
135
|
|
151
136
|
# Guess a specific time within the given span
|
@@ -159,83 +144,6 @@ module Chronic
|
|
159
144
|
end
|
160
145
|
end
|
161
146
|
|
162
|
-
class Token #:nodoc:
|
163
|
-
attr_accessor :word, :tags
|
164
|
-
|
165
|
-
def initialize(word)
|
166
|
-
@word = word
|
167
|
-
@tags = []
|
168
|
-
end
|
169
|
-
|
170
|
-
# Tag this token with the specified tag
|
171
|
-
def tag(new_tag)
|
172
|
-
@tags << new_tag
|
173
|
-
end
|
174
|
-
|
175
|
-
# Remove all tags of the given class
|
176
|
-
def untag(tag_class)
|
177
|
-
@tags = @tags.select { |m| !m.kind_of? tag_class }
|
178
|
-
end
|
179
|
-
|
180
|
-
# Return true if this token has any tags
|
181
|
-
def tagged?
|
182
|
-
@tags.size > 0
|
183
|
-
end
|
184
|
-
|
185
|
-
# Return the Tag that matches the given class
|
186
|
-
def get_tag(tag_class)
|
187
|
-
matches = @tags.select { |m| m.kind_of? tag_class }
|
188
|
-
#matches.size < 2 || raise("Multiple identical tags found")
|
189
|
-
return matches.first
|
190
|
-
end
|
191
|
-
|
192
|
-
# Print this Token in a pretty way
|
193
|
-
def to_s
|
194
|
-
@word << '(' << @tags.join(', ') << ') '
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
# A Span represents a range of time. Since this class extends
|
199
|
-
# Range, you can use #begin and #end to get the beginning and
|
200
|
-
# ending times of the span (they will be of class Time)
|
201
|
-
class Span < Range
|
202
|
-
# Returns the width of this span in seconds
|
203
|
-
def width
|
204
|
-
(self.end - self.begin).to_i
|
205
|
-
end
|
206
|
-
|
207
|
-
# Add a number of seconds to this span, returning the
|
208
|
-
# resulting Span
|
209
|
-
def +(seconds)
|
210
|
-
Span.new(self.begin + seconds, self.end + seconds)
|
211
|
-
end
|
212
|
-
|
213
|
-
# Subtract a number of seconds to this span, returning the
|
214
|
-
# resulting Span
|
215
|
-
def -(seconds)
|
216
|
-
self + -seconds
|
217
|
-
end
|
218
|
-
|
219
|
-
# Prints this span in a nice fashion
|
220
|
-
def to_s
|
221
|
-
'(' << self.begin.to_s << '..' << self.end.to_s << ')'
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
# Tokens are tagged with subclassed instances of this class when
|
226
|
-
# they match specific criteria
|
227
|
-
class Tag #:nodoc:
|
228
|
-
attr_accessor :type
|
229
|
-
|
230
|
-
def initialize(type)
|
231
|
-
@type = type
|
232
|
-
end
|
233
|
-
|
234
|
-
def start=(s)
|
235
|
-
@now = s
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
147
|
# Internal exception
|
240
148
|
class ChronicPain < Exception #:nodoc:
|
241
149
|
|