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,101 @@
1
+ module Chronic
2
+ class Scalar < Tag
3
+ DAY_PORTIONS = %w( am pm morning afternoon evening night )
4
+
5
+ # Scan an Array of Token objects and apply any necessary Scalar
6
+ # tags to each token.
7
+ #
8
+ # tokens - An Array of tokens to scan.
9
+ # options - The Hash of options specified in Chronic::parse.
10
+ #
11
+ # Returns an Array of tokens.
12
+ def self.scan(tokens, options)
13
+ tokens.each_index do |i|
14
+ if is_scalar?(tokens, i)
15
+ token = tokens[i]
16
+ post_token = tokens[i + 1]
17
+ width = token.word.length
18
+ scalar = token.word.to_i
19
+ token.tag(Scalar.new(scalar, width))
20
+ token.tag(ScalarWide.new(token.word, width)) if width == 4
21
+ token.tag(ScalarSubsecond.new(scalar, width)) if Chronic::Time::could_be_subsecond?(scalar, width)
22
+ token.tag(ScalarSecond.new(scalar, width)) if Chronic::Time::could_be_second?(scalar, width)
23
+ token.tag(ScalarMinute.new(scalar, width)) if Chronic::Time::could_be_minute?(scalar, width)
24
+ token.tag(ScalarHour.new(scalar, width)) if Chronic::Time::could_be_hour?(scalar, width, options[:hours24] == false)
25
+ unless post_token and DAY_PORTIONS.include?(post_token.word)
26
+ token.tag(ScalarDay.new(scalar, width)) if Chronic::Date::could_be_day?(scalar, width)
27
+ token.tag(ScalarMonth.new(scalar, width)) if Chronic::Date::could_be_month?(scalar, width)
28
+ token.tag(ScalarFullYear.new(scalar, width)) if width == 4 and Chronic::Date::could_be_year?(scalar, width)
29
+ if Chronic::Date::could_be_year?(scalar, width)
30
+ year = Chronic::Date::make_year(scalar, options[:ambiguous_year_future_bias])
31
+ token.tag(ScalarYear.new(year.to_i, width))
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def self.is_scalar?(tokens, i)
39
+ tokens[i].word =~ /^\d+$/ and (not tokens[i + 1] or not tokens[i + 1].word =~ /^st|nd|rd|th$/)
40
+ end
41
+
42
+ def to_s
43
+ 'scalar'
44
+ end
45
+ end
46
+
47
+ class ScalarWide < Scalar #:nodoc:
48
+ def to_s
49
+ super << '-wide-' << @type.to_s
50
+ end
51
+ end
52
+
53
+ class ScalarSubsecond < Scalar #:nodoc:
54
+ def to_s
55
+ super << '-subsecond-' << @type.to_s
56
+ end
57
+ end
58
+
59
+ class ScalarSecond < Scalar #:nodoc:
60
+ def to_s
61
+ super << '-second-' << @type.to_s
62
+ end
63
+ end
64
+
65
+ class ScalarMinute < Scalar #:nodoc:
66
+ def to_s
67
+ super << '-minute-' << @type.to_s
68
+ end
69
+ end
70
+
71
+ class ScalarHour < Scalar #:nodoc:
72
+ def to_s
73
+ super << '-hour-' << @type.to_s
74
+ end
75
+ end
76
+
77
+ class ScalarDay < Scalar #:nodoc:
78
+ def to_s
79
+ super << '-day-' << @type.to_s
80
+ end
81
+ end
82
+
83
+ class ScalarMonth < Scalar #:nodoc:
84
+ def to_s
85
+ super << '-month-' << @type.to_s
86
+ end
87
+ end
88
+
89
+ class ScalarYear < Scalar #:nodoc:
90
+ def to_s
91
+ super << '-year-' << @type.to_s
92
+ end
93
+ end
94
+
95
+ class ScalarFullYear < Scalar #:nodoc:
96
+ def to_s
97
+ super << '-fullyear-' << @type.to_s
98
+ end
99
+ end
100
+
101
+ end
@@ -0,0 +1,31 @@
1
+ module Chronic
2
+ class SeasonName < Tag
3
+
4
+ # Scan an Array of Token objects and apply any necessary SeasonName
5
+ # tags to each token.
6
+ #
7
+ # tokens - An Array of tokens to scan.
8
+ # options - The Hash of options specified in Chronic::parse.
9
+ #
10
+ # Returns an Array of tokens.
11
+ def self.scan(tokens, options)
12
+ tokens.each do |token|
13
+ token.tag scan_for(token, self, patterns, options)
14
+ end
15
+ end
16
+
17
+ def self.patterns
18
+ @@patterns ||= {
19
+ /^springs?$/i => :spring,
20
+ /^summers?$/i => :summer,
21
+ /^(autumn)|(fall)s?$/i => :autumn,
22
+ /^winters?$/i => :winter
23
+ }
24
+ end
25
+
26
+ def to_s
27
+ 'seasonname-' << @type.to_s
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,130 @@
1
+ module Chronic
2
+ class Separator < Tag
3
+
4
+ # Scan an Array of Token objects and apply any necessary Separator
5
+ # tags to each token.
6
+ #
7
+ # tokens - An Array of tokens to scan.
8
+ # options - The Hash of options specified in Chronic::parse.
9
+ #
10
+ # Returns an Array of tokens.
11
+ def self.scan(tokens, options)
12
+ tokens.each do |token|
13
+ token.tag scan_for(token, SeparatorComma, { ','.to_sym => :comma })
14
+ token.tag scan_for(token, SeparatorDot, { '.'.to_sym => :dot })
15
+ token.tag scan_for(token, SeparatorColon, { ':'.to_sym => :colon })
16
+ token.tag scan_for(token, SeparatorSpace, { ' '.to_sym => :space })
17
+ token.tag scan_for(token, SeparatorSlash, { '/'.to_sym => :slash })
18
+ token.tag scan_for(token, SeparatorApostrophe, { '\''.to_sym => :apostrophe })
19
+ token.tag scan_for(token, SeparatorDash, { :- => :dash })
20
+ token.tag scan_for(token, SeparatorAt, { /^(at|@)$/i => :at })
21
+ token.tag scan_for(token, SeparatorIn, { 'in' => :in })
22
+ token.tag scan_for(token, SeparatorOn, { 'on' => :on })
23
+ token.tag scan_for(token, SeparatorAnd, { 'and' => :and })
24
+ token.tag scan_for(token, SeparatorT, { :T => :T })
25
+ token.tag scan_for(token, SeparatorW, { :W => :W })
26
+ token.tag scan_for_quote(token)
27
+ end
28
+ end
29
+
30
+ # token - The Token object we want to scan.
31
+ #
32
+ # Returns a new SeparatorQuote object.
33
+ def self.scan_for_quote(token)
34
+ scan_for token, SeparatorQuote,
35
+ {
36
+ "'".to_sym => :single_quote,
37
+ '"'.to_sym => :double_quote
38
+ }
39
+ end
40
+
41
+ def to_s
42
+ 'separator'
43
+ end
44
+ end
45
+
46
+ class SeparatorComma < Separator #:nodoc:
47
+ def to_s
48
+ super << '-comma'
49
+ end
50
+ end
51
+
52
+ class SeparatorDot < Separator #:nodoc:
53
+ def to_s
54
+ super << '-dot'
55
+ end
56
+ end
57
+
58
+ class SeparatorColon < Separator #:nodoc:
59
+ def to_s
60
+ super << '-colon'
61
+ end
62
+ end
63
+
64
+ class SeparatorSpace < Separator #:nodoc:
65
+ def to_s
66
+ super << '-space'
67
+ end
68
+ end
69
+
70
+ class SeparatorSlash < Separator #:nodoc:
71
+ def to_s
72
+ super << '-slash'
73
+ end
74
+ end
75
+
76
+ class SeparatorDash < Separator #:nodoc:
77
+ def to_s
78
+ super << '-dash'
79
+ end
80
+ end
81
+
82
+ class SeparatorQuote < Separator #:nodoc:
83
+ def to_s
84
+ super << '-quote-' << @type.to_s
85
+ end
86
+ end
87
+
88
+ class SeparatorApostrophe < Separator #:nodoc:
89
+ def to_s
90
+ super << '-apostrophe-' << @type.to_s
91
+ end
92
+ end
93
+
94
+ class SeparatorAt < Separator #:nodoc:
95
+ def to_s
96
+ super << '-at'
97
+ end
98
+ end
99
+
100
+ class SeparatorIn < Separator #:nodoc:
101
+ def to_s
102
+ super << '-in'
103
+ end
104
+ end
105
+
106
+ class SeparatorOn < Separator #:nodoc:
107
+ def to_s
108
+ super << '-on'
109
+ end
110
+ end
111
+
112
+ class SeparatorAnd < Separator #:nodoc:
113
+ def to_s
114
+ super << '-and'
115
+ end
116
+ end
117
+
118
+ class SeparatorT < Separator #:nodoc:
119
+ def to_s
120
+ super << '-T'
121
+ end
122
+ end
123
+
124
+ class SeparatorW < Separator #:nodoc:
125
+ def to_s
126
+ super << '-W'
127
+ end
128
+ end
129
+
130
+ end
@@ -0,0 +1,35 @@
1
+ module Chronic
2
+ class Sign < Tag
3
+
4
+ # Scan an Array of Token objects and apply any necessary Sign
5
+ # tags to each token.
6
+ #
7
+ # tokens - An Array of tokens to scan.
8
+ # options - The Hash of options specified in Chronic::parse.
9
+ #
10
+ # Returns an Array of tokens.
11
+ def self.scan(tokens, options)
12
+ tokens.each do |token|
13
+ token.tag scan_for(token, SignPlus, { :+ => :plus })
14
+ token.tag scan_for(token, SignMinus, { :- => :minus })
15
+ end
16
+ end
17
+
18
+ def to_s
19
+ 'sign'
20
+ end
21
+ end
22
+
23
+ class SignPlus < Sign #:nodoc:
24
+ def to_s
25
+ super << '-plus'
26
+ end
27
+ end
28
+
29
+ class SignMinus < Sign #:nodoc:
30
+ def to_s
31
+ super << '-minus'
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,34 @@
1
+ module Chronic
2
+ class TimeSpecial < Tag
3
+
4
+ # Scan an Array of Token objects and apply any necessary TimeSpecial
5
+ # tags to each token.
6
+ #
7
+ # tokens - An Array of tokens to scan.
8
+ # options - The Hash of options specified in Chronic::parse.
9
+ #
10
+ # Returns an Array of tokens.
11
+ def self.scan(tokens, options)
12
+ tokens.each do |token|
13
+ token.tag scan_for(token, self, patterns, options)
14
+ end
15
+ end
16
+
17
+ def self.patterns
18
+ @@patterns ||= {
19
+ 'now' => :now,
20
+ 'morning' => :morning,
21
+ 'noon' => :noon,
22
+ 'afternoon' => :afternoon,
23
+ 'evening' => :evening,
24
+ /^(to)?(night|nite)$/ => :night,
25
+ 'midnight' => :midnight
26
+ }
27
+ end
28
+
29
+ def to_s
30
+ 'timespecial-' << @type.to_s
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,56 @@
1
+ module Chronic
2
+ class TimeZoneTag < Tag
3
+
4
+ # Scan an Array of Token objects and apply any necessary TimeZoneTag
5
+ # tags to each token.
6
+ #
7
+ # tokens - An Array of tokens to scan.
8
+ # options - The Hash of options specified in Chronic::parse.
9
+ #
10
+ # Returns an Array of tokens.
11
+ def self.scan(tokens, options)
12
+ tokens.each_index do |i|
13
+ token = tokens[i]
14
+ token.tag scan_for(token, TimeZoneGeneric, patterns)
15
+ token.tag TimeZoneAbbreviation.new(token.word, nil, options) if TimeZone::is_valid_abbr?(token.word)
16
+ end
17
+ end
18
+
19
+ def self.patterns
20
+ @@patterns ||= {
21
+ :UTC => 0,
22
+ :Z => 0
23
+ }
24
+ end
25
+
26
+ def to_s
27
+ 'timezone'
28
+ end
29
+
30
+ end
31
+
32
+ class TimeZoneGeneric < TimeZoneTag #:nodoc:
33
+ def to_s
34
+ super + '-generic-' + @type.to_s
35
+ end
36
+ end
37
+
38
+ class TimeZoneAbbreviation < TimeZoneTag #:nodoc:
39
+ def to_s
40
+ super + '-abbr-' + @type.to_s
41
+ end
42
+ end
43
+
44
+ class TimeZoneName < TimeZoneTag #:nodoc:
45
+ def to_s
46
+ super + '-name-' + @type.to_s
47
+ end
48
+ end
49
+
50
+ class TimeZoneTZ < TimeZoneTag #:nodoc:
51
+ def to_s
52
+ super + '-tz-' + @type.to_s
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,174 @@
1
+ module Chronic
2
+ class Unit < Tag
3
+
4
+ # Scan an Array of Token objects and apply any necessary Unit
5
+ # tags to each token.
6
+ #
7
+ # tokens - An Array of tokens to scan.
8
+ # options - The Hash of options specified in Chronic::parse.
9
+ #
10
+ # Returns an Array of tokens.
11
+ def self.scan(tokens, options)
12
+ tokens.each do |token|
13
+ token.tag scan_for_units(token, options)
14
+ end
15
+ end
16
+
17
+ # token - The Token object we want to scan.
18
+ #
19
+ # Returns a new Unit object.
20
+ def self.scan_for_units(token, options = {})
21
+ patterns.each do |item, symbol|
22
+ if item =~ token.word
23
+ klass_name = 'Unit' + symbol.to_s.capitalize
24
+ klass = Chronic.const_get(klass_name)
25
+ return klass.new(symbol, options)
26
+ end
27
+ end
28
+ return nil
29
+ end
30
+
31
+ def self.patterns
32
+ @@paterns ||= {
33
+ /^years?$/i => :year,
34
+ /^seasons?$/i => :season,
35
+ /^quarters?$/i => :quarter,
36
+ /^months?$/i => :month,
37
+ /^fortnights?$/i => :fortnight,
38
+ /^weeks?$/i => :week,
39
+ /^weekends?$/i => :weekend,
40
+ /^(week|business)days?$/i => :weekday,
41
+ /^days?$/i => :day,
42
+ /^mornings?$/i => :morning,
43
+ /^noons?$/ => :noon,
44
+ /^afternoons?$/i => :afternoon,
45
+ /^evenings?$/i => :evening,
46
+ /^(to)?(night|nite)s?$/i => :night,
47
+ /^midnights?$/i => :midnight,
48
+ /^(hr|hour)s?$/i => :hour,
49
+ /^(min|minute)s?$/i => :minute,
50
+ /^(sec|second)s?$/i => :second,
51
+ /^(ms|miliseconds?)$/i => :milisecond
52
+ }
53
+ end
54
+
55
+ def to_s
56
+ 'unit'
57
+ end
58
+ end
59
+
60
+ class UnitYear < Unit #:nodoc:
61
+ def to_s
62
+ super << '-year'
63
+ end
64
+ end
65
+
66
+ class UnitSeason < Unit #:nodoc:
67
+ def to_s
68
+ super << '-season'
69
+ end
70
+ end
71
+
72
+ class UnitQuarter < Unit #:nodoc:
73
+ def to_s
74
+ super << '-quarter'
75
+ end
76
+ end
77
+
78
+ class UnitMonth < Unit #:nodoc:
79
+ def to_s
80
+ super << '-month'
81
+ end
82
+ end
83
+
84
+ class UnitFortnight < Unit #:nodoc:
85
+ def to_s
86
+ super << '-fortnight'
87
+ end
88
+ end
89
+
90
+ class UnitWeek < Unit #:nodoc:
91
+ def to_s
92
+ super << '-week'
93
+ end
94
+ end
95
+
96
+ class UnitWeekend < Unit #:nodoc:
97
+ def to_s
98
+ super << '-weekend'
99
+ end
100
+ end
101
+
102
+ class UnitWeekday < Unit #:nodoc:
103
+ def to_s
104
+ super << '-weekday'
105
+ end
106
+ end
107
+
108
+ class UnitDay < Unit #:nodoc:
109
+ def to_s
110
+ super << '-day'
111
+ end
112
+ end
113
+
114
+ class UnitMorning < Unit #:nodoc:
115
+ def to_s
116
+ super << '-morning'
117
+ end
118
+ end
119
+
120
+ class UnitNoon < Unit #:nodoc:
121
+ def to_s
122
+ super << '-noon'
123
+ end
124
+ end
125
+
126
+ class UnitAfternoon < Unit #:nodoc:
127
+ def to_s
128
+ super << '-afternoon'
129
+ end
130
+ end
131
+
132
+ class UnitEvening < Unit #:nodoc:
133
+ def to_s
134
+ super << '-evening'
135
+ end
136
+ end
137
+
138
+ class UnitNight < Unit #:nodoc:
139
+ def to_s
140
+ super << '-night'
141
+ end
142
+ end
143
+
144
+ class UnitMidnight < Unit #:nodoc:
145
+ def to_s
146
+ super << '-night'
147
+ end
148
+ end
149
+
150
+ class UnitHour < Unit #:nodoc:
151
+ def to_s
152
+ super << '-hour'
153
+ end
154
+ end
155
+
156
+ class UnitMinute < Unit #:nodoc:
157
+ def to_s
158
+ super << '-minute'
159
+ end
160
+ end
161
+
162
+ class UnitSecond < Unit #:nodoc:
163
+ def to_s
164
+ super << '-second'
165
+ end
166
+ end
167
+
168
+ class UnitMilisecond < Unit #:nodoc:
169
+ def to_s
170
+ super << '-milisecond'
171
+ end
172
+ end
173
+
174
+ end