pangel-chronic 0.3.0.3 → 0.3.10

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 (47) hide show
  1. data/{README.rdoc → README.txt} +7 -22
  2. data/lib/chronic.rb +89 -12
  3. data/lib/chronic/chronic.rb +260 -301
  4. data/lib/chronic/grabber.rb +23 -23
  5. data/lib/chronic/handlers.rb +538 -557
  6. data/lib/chronic/ordinal.rb +36 -35
  7. data/lib/chronic/pointer.rb +24 -26
  8. data/lib/chronic/repeater.rb +128 -138
  9. data/lib/chronic/repeaters/repeater_day.rb +51 -51
  10. data/lib/chronic/repeaters/repeater_day_name.rb +50 -52
  11. data/lib/chronic/repeaters/repeater_day_portion.rb +93 -93
  12. data/lib/chronic/repeaters/repeater_fortnight.rb +66 -66
  13. data/lib/chronic/repeaters/repeater_hour.rb +56 -57
  14. data/lib/chronic/repeaters/repeater_minute.rb +56 -56
  15. data/lib/chronic/repeaters/repeater_month.rb +71 -62
  16. data/lib/chronic/repeaters/repeater_month_name.rb +95 -95
  17. data/lib/chronic/repeaters/repeater_season.rb +142 -142
  18. data/lib/chronic/repeaters/repeater_season_name.rb +42 -42
  19. data/lib/chronic/repeaters/repeater_second.rb +40 -40
  20. data/lib/chronic/repeaters/repeater_time.rb +124 -123
  21. data/lib/chronic/repeaters/repeater_week.rb +70 -70
  22. data/lib/chronic/repeaters/repeater_weekday.rb +76 -76
  23. data/lib/chronic/repeaters/repeater_weekend.rb +63 -63
  24. data/lib/chronic/repeaters/repeater_year.rb +63 -63
  25. data/lib/chronic/scalar.rb +89 -70
  26. data/lib/chronic/separator.rb +88 -88
  27. data/lib/chronic/time_zone.rb +23 -20
  28. data/lib/numerizer/numerizer.rb +93 -94
  29. data/test/suite.rb +2 -2
  30. data/test/test_Chronic.rb +47 -47
  31. data/test/test_Handler.rb +106 -106
  32. data/test/test_Numerizer.rb +47 -49
  33. data/test/test_RepeaterDayName.rb +48 -48
  34. data/test/test_RepeaterFortnight.rb +59 -59
  35. data/test/test_RepeaterHour.rb +61 -64
  36. data/test/test_RepeaterMonth.rb +43 -43
  37. data/test/test_RepeaterMonthName.rb +53 -53
  38. data/test/test_RepeaterTime.rb +68 -68
  39. data/test/test_RepeaterWeek.rb +59 -59
  40. data/test/test_RepeaterWeekday.rb +53 -53
  41. data/test/test_RepeaterWeekend.rb +71 -71
  42. data/test/test_RepeaterYear.rb +59 -59
  43. data/test/test_Span.rb +19 -28
  44. data/test/test_Time.rb +46 -46
  45. data/test/test_Token.rb +22 -22
  46. data/test/test_parsing.rb +726 -792
  47. metadata +6 -10
@@ -1,39 +1,40 @@
1
1
  module Chronic
2
2
 
3
- class Ordinal < Tag #:nodoc:
4
- def self.scan(tokens)
5
- # for each token
6
- tokens.each_index do |i|
7
- if t = self.scan_for_ordinals(tokens[i]) then tokens[i].tag(t) end
8
- if t = self.scan_for_days(tokens[i]) then tokens[i].tag(t) end
9
- end
10
- tokens
11
- end
3
+ class Ordinal < Tag #:nodoc:
4
+ def self.scan(tokens)
5
+ # for each token
6
+ tokens.each_index do |i|
7
+ if t = self.scan_for_ordinals(tokens[i]) then tokens[i].tag(t) end
8
+ if t = self.scan_for_days(tokens[i]) then tokens[i].tag(t) end
9
+ end
10
+ tokens
11
+ end
12
+
13
+ def self.scan_for_ordinals(token)
14
+ if token.word =~ /^(\d*)(st|nd|rd|th)$/
15
+ return Ordinal.new($1.to_i)
16
+ end
17
+ return nil
18
+ end
19
+
20
+ def self.scan_for_days(token)
21
+ if token.word =~ /^(\d*)(st|nd|rd|th)$/
22
+ unless $1.to_i > 31 || $1.to_i < 1
23
+ return OrdinalDay.new(token.word.to_i)
24
+ end
25
+ end
26
+ return nil
27
+ end
28
+
29
+ def to_s
30
+ 'ordinal'
31
+ end
32
+ end
33
+
34
+ class OrdinalDay < Ordinal #:nodoc:
35
+ def to_s
36
+ super << '-day-' << @type.to_s
37
+ end
38
+ end
12
39
 
13
- def self.scan_for_ordinals(token)
14
- if token.word =~ /^(\d*)(st|nd|rd|th)$/i
15
- return Ordinal.new($1.to_i)
16
- end
17
- return nil
18
- end
19
-
20
- def self.scan_for_days(token)
21
- if token.word =~ /^(\d*)(st|nd|rd|th)$/i
22
- unless $1.to_i > 31 || $1.to_i < 1
23
- return OrdinalDay.new(token.word.to_i)
24
- end
25
- end
26
- return nil
27
- end
28
-
29
- def to_s
30
- 'ordinal'
31
- end
32
- end
33
-
34
- class OrdinalDay < Ordinal #:nodoc:
35
- def to_s
36
- super << '-day-' << @type.to_s
37
- end
38
- end
39
40
  end
@@ -1,29 +1,27 @@
1
1
  module Chronic
2
2
 
3
- class Pointer < Tag #:nodoc:
4
- def self.scan(tokens)
5
- # for each token
6
- tokens.each_index do |i|
7
- if t = self.scan_for_all(tokens[i]) then tokens[i].tag(t) end
8
- end
9
- tokens
10
- end
3
+ class Pointer < Tag #:nodoc:
4
+ def self.scan(tokens)
5
+ # for each token
6
+ tokens.each_index do |i|
7
+ if t = self.scan_for_all(tokens[i]) then tokens[i].tag(t) end
8
+ end
9
+ tokens
10
+ end
11
+
12
+ def self.scan_for_all(token)
13
+ scanner = {/\bpast\b/ => :past,
14
+ /\bfuture\b/ => :future,
15
+ /\bin\b/ => :future}
16
+ scanner.keys.each do |scanner_item|
17
+ return self.new(scanner[scanner_item]) if scanner_item =~ token.word
18
+ end
19
+ return nil
20
+ end
21
+
22
+ def to_s
23
+ 'pointer-' << @type.to_s
24
+ end
25
+ end
11
26
 
12
- def self.scan_for_all(token)
13
- scanner = {/\bpast\b/i => :past,
14
- /\bfuture\b/i => :future,
15
- /\bfor\b/i => :future,
16
- /\bin\b/i => :future}
17
-
18
- scanner.keys.each do |scanner_item|
19
- return self.new(scanner[scanner_item]) if scanner_item =~ token.word
20
- end
21
- return nil
22
- end
23
-
24
- def to_s
25
- 'pointer-' << @type.to_s
26
- end
27
- end
28
-
29
- end
27
+ end
@@ -1,139 +1,129 @@
1
1
  class Chronic::Repeater < Chronic::Tag #:nodoc:
2
- def self.scan(tokens, options)
3
- # for each token
4
- tokens.each_index do |i|
5
- if t = self.scan_for_season_names(tokens[i]) then tokens[i].tag(t); next end
6
- if t = self.scan_for_month_names(tokens[i]) then tokens[i].tag(t); next end
7
- if t = self.scan_for_day_names(tokens[i]) then tokens[i].tag(t); next end
8
- if t = self.scan_for_day_portions(tokens[i]) then tokens[i].tag(t); next end
9
- if t = self.scan_for_times(tokens[i], options) then tokens[i].tag(t); next end
10
- if t = self.scan_for_units(tokens[i]) then tokens[i].tag(t); next end
11
- if t = self.scan_for_decades(tokens[i]) then tokens[i].tag(t); next end
12
- end
13
- tokens
14
- end
15
-
16
- def self.scan_for_season_names(token)
17
- scanner = {/^springs?$/i => :spring,
18
- /^summers?$/i => :summer,
19
- /^(autumn)|(fall)s?$/i => :autumn,
20
- /^winters?$/i => :winter}
21
- scanner.keys.each do |scanner_item|
22
- return Chronic::RepeaterSeasonName.new(scanner[scanner_item]) if scanner_item =~ token.word
23
- end
24
-
25
- return nil
26
- end
27
-
28
- def self.scan_for_month_names(token)
29
- scanner = {/^jan\.?(uary)?$/i => :january,
30
- /^feb\.?(ruary)?$/i => :february,
31
- /^mar\.?(ch)?$/i => :march,
32
- /^apr\.?(il)?$/i => :april,
33
- /^may$/i => :may,
34
- /^jun\.?e?$/i => :june,
35
- /^jul\.?y?$/i => :july,
36
- /^aug\.?(ust)?$/i => :august,
37
- /^sep\.?(t\.?|tember)?$/i => :september,
38
- /^oct\.?(ober)?$/i => :october,
39
- /^nov\.?(ember)?$/i => :november,
40
- /^dec\.?(ember)?$/i => :december}
41
- scanner.keys.each do |scanner_item|
42
- return Chronic::RepeaterMonthName.new(scanner[scanner_item]) if scanner_item =~ token.word
43
- end
44
- return nil
45
- end
46
-
47
- def self.scan_for_day_names(token)
48
- scanner = {/^m[ou]n(day)?$/i => :monday,
49
- /^t(ue|eu|oo|u|)s(day)?$/i => :tuesday,
50
- /^tue$/i => :tuesday,
51
- /^we(dnes|nds|nns)day$/i => :wednesday,
52
- /^wed$/i => :wednesday,
53
- /^th(urs|ers)day$/i => :thursday,
54
- /^thu$/i => :thursday,
55
- /^fr[iy](day)?$/i => :friday,
56
- /^sat(t?[ue]rday)?$/i => :saturday,
57
- /^su[nm](day)?$/i => :sunday}
58
- scanner.keys.each do |scanner_item|
59
- return Chronic::RepeaterDayName.new(scanner[scanner_item]) if scanner_item =~ token.word
60
- end
61
- return nil
62
- end
63
-
64
- def self.scan_for_day_portions(token)
65
- puts "scan_for_day_portions -- #{token}" if Chronic.debug
66
- scanner = {/^ams?$/i => :am,
67
- /^pms?$/i => :pm,
68
- /^mornings?$/i => :morning,
69
- /^afternoons?$/i => :afternoon,
70
- /^evenings?$/i => :evening,
71
- /^(night|nite)s?$/i => :night}
72
- scanner.keys.each do |scanner_item|
73
- return Chronic::RepeaterDayPortion.new(scanner[scanner_item]) if scanner_item =~ token.word
74
- end
75
- return nil
76
- end
77
-
78
- def self.scan_for_times(token, options)
79
- if token.word =~ /^\d{1,2}(:?\d{2})?([\.:]?\d{2})?$/
80
- return Chronic::RepeaterTime.new(token.word, options)
81
- end
82
- return nil
83
- end
84
-
85
- def self.scan_for_decades(token)
86
- if token.word =~ Chronic::RepeaterDecade::DECADE_PATTERN
87
- return Chronic::RepeaterDecade.new(token.word)
88
- end
89
- return nil
90
- end
91
-
92
- def self.scan_for_units(token)
93
- scanner = {/^years?$/i => :year,
94
- /^seasons?$/i => :season,
95
- /^months?$/i => :month,
96
- /^fortnights?$/i => :fortnight,
97
- /^weeks?$/i => :week,
98
- /^weekends?$/i => :weekend,
99
- /^(week|business)days?$/i => :weekday,
100
- /^days?$/i => :day,
101
- /^hours?$/i => :hour,
102
- /^minutes?$/i => :minute,
103
- /^seconds?$/i => :second,
104
- }
105
- scanner.keys.each do |scanner_item|
106
- if scanner_item =~ token.word
107
- klass_name = 'Chronic::Repeater' + scanner[scanner_item].to_s.capitalize
108
- klass = eval(klass_name)
109
- return klass.new(scanner[scanner_item])
110
- end
111
- end
112
- return nil
113
- end
114
-
115
- def <=>(other)
116
- width <=> other.width
117
- end
118
-
119
- # returns the width (in seconds or months) of this repeatable.
120
- def width
121
- raise("Repeatable#width must be overridden in subclasses")
122
- end
123
-
124
- # returns the next occurance of this repeatable.
125
- def next(pointer)
126
- !@now.nil? || raise("Start point must be set before calling #next")
127
- [:future, :none, :past].include?(pointer) || raise("First argument 'pointer' must be one of :past or :future")
128
- #raise("Repeatable#next must be overridden in subclasses")
129
- end
130
-
131
- def this(pointer)
132
- !@now.nil? || raise("Start point must be set before calling #this")
133
- [:future, :past, :none].include?(pointer) || raise("First argument 'pointer' must be one of :past, :future, :none")
134
- end
135
-
136
- def to_s
137
- 'repeater'
138
- end
139
- end
2
+ def self.scan(tokens, options)
3
+ # for each token
4
+ tokens.each_index do |i|
5
+ if t = self.scan_for_season_names(tokens[i]) then tokens[i].tag(t); next end
6
+ if t = self.scan_for_month_names(tokens[i]) then tokens[i].tag(t); next end
7
+ if t = self.scan_for_day_names(tokens[i]) then tokens[i].tag(t); next end
8
+ if t = self.scan_for_day_portions(tokens[i]) then tokens[i].tag(t); next end
9
+ if t = self.scan_for_times(tokens[i], options) then tokens[i].tag(t); next end
10
+ if t = self.scan_for_units(tokens[i]) then tokens[i].tag(t); next end
11
+ end
12
+ tokens
13
+ end
14
+
15
+ def self.scan_for_season_names(token)
16
+ scanner = {/^springs?$/ => :spring,
17
+ /^summers?$/ => :summer,
18
+ /^(autumn)|(fall)s?$/ => :autumn,
19
+ /^winters?$/ => :winter}
20
+ scanner.keys.each do |scanner_item|
21
+ return Chronic::RepeaterSeasonName.new(scanner[scanner_item]) if scanner_item =~ token.word
22
+ end
23
+
24
+ return nil
25
+ end
26
+
27
+ def self.scan_for_month_names(token)
28
+ scanner = {/^jan\.?(uary)?$/ => :january,
29
+ /^feb\.?(ruary)?$/ => :february,
30
+ /^mar\.?(ch)?$/ => :march,
31
+ /^apr\.?(il)?$/ => :april,
32
+ /^may$/ => :may,
33
+ /^jun\.?e?$/ => :june,
34
+ /^jul\.?y?$/ => :july,
35
+ /^aug\.?(ust)?$/ => :august,
36
+ /^sep\.?(t\.?|tember)?$/ => :september,
37
+ /^oct\.?(ober)?$/ => :october,
38
+ /^nov\.?(ember)?$/ => :november,
39
+ /^dec\.?(ember)?$/ => :december}
40
+ scanner.keys.each do |scanner_item|
41
+ return Chronic::RepeaterMonthName.new(scanner[scanner_item]) if scanner_item =~ token.word
42
+ end
43
+ return nil
44
+ end
45
+
46
+ def self.scan_for_day_names(token)
47
+ scanner = {/^m[ou]n(day)?$/ => :monday,
48
+ /^t(ue|eu|oo|u|)s(day)?$/ => :tuesday,
49
+ /^tue$/ => :tuesday,
50
+ /^we(dnes|nds|nns)day$/ => :wednesday,
51
+ /^wed$/ => :wednesday,
52
+ /^th(urs|ers)day$/ => :thursday,
53
+ /^thu$/ => :thursday,
54
+ /^fr[iy](day)?$/ => :friday,
55
+ /^sat(t?[ue]rday)?$/ => :saturday,
56
+ /^su[nm](day)?$/ => :sunday}
57
+ scanner.keys.each do |scanner_item|
58
+ return Chronic::RepeaterDayName.new(scanner[scanner_item]) if scanner_item =~ token.word
59
+ end
60
+ return nil
61
+ end
62
+
63
+ def self.scan_for_day_portions(token)
64
+ scanner = {/^ams?$/ => :am,
65
+ /^pms?$/ => :pm,
66
+ /^mornings?$/ => :morning,
67
+ /^afternoons?$/ => :afternoon,
68
+ /^evenings?$/ => :evening,
69
+ /^(night|nite)s?$/ => :night}
70
+ scanner.keys.each do |scanner_item|
71
+ return Chronic::RepeaterDayPortion.new(scanner[scanner_item]) if scanner_item =~ token.word
72
+ end
73
+ return nil
74
+ end
75
+
76
+ def self.scan_for_times(token, options)
77
+ if token.word =~ /^\d{1,2}(:?\d{2})?([\.:]?\d{2})?$/
78
+ return Chronic::RepeaterTime.new(token.word, options)
79
+ end
80
+ return nil
81
+ end
82
+
83
+ def self.scan_for_units(token)
84
+ scanner = {/^years?$/ => :year,
85
+ /^seasons?$/ => :season,
86
+ /^months?$/ => :month,
87
+ /^fortnights?$/ => :fortnight,
88
+ /^weeks?$/ => :week,
89
+ /^weekends?$/ => :weekend,
90
+ /^(week|business)days?$/ => :weekday,
91
+ /^days?$/ => :day,
92
+ /^hours?$/ => :hour,
93
+ /^minutes?$/ => :minute,
94
+ /^seconds?$/ => :second}
95
+ scanner.keys.each do |scanner_item|
96
+ if scanner_item =~ token.word
97
+ klass_name = 'Chronic::Repeater' + scanner[scanner_item].to_s.capitalize
98
+ klass = eval(klass_name)
99
+ return klass.new(scanner[scanner_item])
100
+ end
101
+ end
102
+ return nil
103
+ end
104
+
105
+ def <=>(other)
106
+ width <=> other.width
107
+ end
108
+
109
+ # returns the width (in seconds or months) of this repeatable.
110
+ def width
111
+ raise("Repeatable#width must be overridden in subclasses")
112
+ end
113
+
114
+ # returns the next occurance of this repeatable.
115
+ def next(pointer)
116
+ !@now.nil? || raise("Start point must be set before calling #next")
117
+ [:future, :none, :past].include?(pointer) || raise("First argument 'pointer' must be one of :past or :future")
118
+ #raise("Repeatable#next must be overridden in subclasses")
119
+ end
120
+
121
+ def this(pointer)
122
+ !@now.nil? || raise("Start point must be set before calling #this")
123
+ [:future, :past, :none].include?(pointer) || raise("First argument 'pointer' must be one of :past, :future, :none")
124
+ end
125
+
126
+ def to_s
127
+ 'repeater'
128
+ end
129
+ end
@@ -1,52 +1,52 @@
1
1
  class Chronic::RepeaterDay < Chronic::Repeater #:nodoc:
2
- DAY_SECONDS = 86_400 # (24 * 60 * 60)
3
-
4
- def initialize(type)
5
- super
6
- @current_day_start = nil
7
- end
8
-
9
- def next(pointer)
10
- super
11
-
12
- if !@current_day_start
13
- @current_day_start = Chronic.time_class.local(@now.year, @now.month, @now.day)
14
- end
15
-
16
- direction = pointer == :future ? 1 : -1
17
- @current_day_start += direction * DAY_SECONDS
18
-
19
- Chronic::Span.new(@current_day_start, @current_day_start + DAY_SECONDS)
20
- end
21
-
22
- def this(pointer = :future)
23
- super
24
-
25
- case pointer
26
- when :future
27
- day_begin = Time.construct(@now.year, @now.month, @now.day, @now.hour + 1)
28
- day_end = Time.construct(@now.year, @now.month, @now.day) + DAY_SECONDS
29
- when :past
30
- day_begin = Time.construct(@now.year, @now.month, @now.day)
31
- day_end = Time.construct(@now.year, @now.month, @now.day, @now.hour)
32
- when :none
33
- day_begin = Time.construct(@now.year, @now.month, @now.day)
34
- day_end = Time.construct(@now.year, @now.month, @now.day) + DAY_SECONDS
35
- end
36
-
37
- Chronic::Span.new(day_begin, day_end)
38
- end
39
-
40
- def offset(span, amount, pointer)
41
- direction = pointer == :future ? 1 : -1
42
- span + direction * amount * DAY_SECONDS
43
- end
44
-
45
- def width
46
- DAY_SECONDS
47
- end
48
-
49
- def to_s
50
- super << '-day'
51
- end
52
- end
2
+ DAY_SECONDS = 86_400 # (24 * 60 * 60)
3
+
4
+ def initialize(type)
5
+ super
6
+ @current_day_start = nil
7
+ end
8
+
9
+ def next(pointer)
10
+ super
11
+
12
+ if !@current_day_start
13
+ @current_day_start = Chronic.time_class.local(@now.year, @now.month, @now.day)
14
+ end
15
+
16
+ direction = pointer == :future ? 1 : -1
17
+ @current_day_start += direction * DAY_SECONDS
18
+
19
+ Chronic::Span.new(@current_day_start, @current_day_start + DAY_SECONDS)
20
+ end
21
+
22
+ def this(pointer = :future)
23
+ super
24
+
25
+ case pointer
26
+ when :future
27
+ day_begin = Time.construct(@now.year, @now.month, @now.day, @now.hour + 1)
28
+ day_end = Time.construct(@now.year, @now.month, @now.day) + DAY_SECONDS
29
+ when :past
30
+ day_begin = Time.construct(@now.year, @now.month, @now.day)
31
+ day_end = Time.construct(@now.year, @now.month, @now.day, @now.hour)
32
+ when :none
33
+ day_begin = Time.construct(@now.year, @now.month, @now.day)
34
+ day_end = Time.construct(@now.year, @now.month, @now.day) + DAY_SECONDS
35
+ end
36
+
37
+ Chronic::Span.new(day_begin, day_end)
38
+ end
39
+
40
+ def offset(span, amount, pointer)
41
+ direction = pointer == :future ? 1 : -1
42
+ span + direction * amount * DAY_SECONDS
43
+ end
44
+
45
+ def width
46
+ DAY_SECONDS
47
+ end
48
+
49
+ def to_s
50
+ super << '-day'
51
+ end
52
+ end