chronic-davispuh 0.10.2.v0.1da32066b3f46f2506b3471e39557497e34afa27

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 (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