chronic 0.2.2 → 0.10.2

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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.travis.yml +8 -0
  4. data/HISTORY.md +243 -0
  5. data/LICENSE +21 -0
  6. data/README.md +182 -0
  7. data/Rakefile +62 -15
  8. data/chronic.gemspec +23 -0
  9. data/lib/chronic/date.rb +82 -0
  10. data/lib/chronic/grabber.rb +24 -17
  11. data/lib/chronic/handler.rb +97 -0
  12. data/lib/chronic/handlers.rb +490 -312
  13. data/lib/chronic/mini_date.rb +38 -0
  14. data/lib/chronic/numerizer.rb +130 -0
  15. data/lib/chronic/ordinal.rb +33 -24
  16. data/lib/chronic/parser.rb +268 -0
  17. data/lib/chronic/pointer.rb +22 -17
  18. data/lib/chronic/repeater.rb +137 -107
  19. data/lib/chronic/repeaters/repeater_day.rb +51 -44
  20. data/lib/chronic/repeaters/repeater_day_name.rb +50 -43
  21. data/lib/chronic/repeaters/repeater_day_portion.rb +97 -81
  22. data/lib/chronic/repeaters/repeater_fortnight.rb +61 -54
  23. data/lib/chronic/repeaters/repeater_hour.rb +51 -44
  24. data/lib/chronic/repeaters/repeater_minute.rb +51 -44
  25. data/lib/chronic/repeaters/repeater_month.rb +79 -60
  26. data/lib/chronic/repeaters/repeater_month_name.rb +85 -83
  27. data/lib/chronic/repeaters/repeater_season.rb +110 -22
  28. data/lib/chronic/repeaters/repeater_season_name.rb +41 -22
  29. data/lib/chronic/repeaters/repeater_second.rb +41 -34
  30. data/lib/chronic/repeaters/repeater_time.rb +128 -104
  31. data/lib/chronic/repeaters/repeater_week.rb +65 -58
  32. data/lib/chronic/repeaters/repeater_weekday.rb +86 -0
  33. data/lib/chronic/repeaters/repeater_weekend.rb +59 -52
  34. data/lib/chronic/repeaters/repeater_year.rb +72 -52
  35. data/lib/chronic/scalar.rb +53 -46
  36. data/lib/chronic/season.rb +26 -0
  37. data/lib/chronic/separator.rb +174 -43
  38. data/lib/chronic/sign.rb +49 -0
  39. data/lib/chronic/span.rb +31 -0
  40. data/lib/chronic/tag.rb +37 -0
  41. data/lib/chronic/time.rb +40 -0
  42. data/lib/chronic/time_zone.rb +21 -11
  43. data/lib/chronic/token.rb +51 -0
  44. data/lib/chronic.rb +94 -69
  45. data/test/helper.rb +12 -0
  46. data/test/test_chronic.rb +183 -0
  47. data/test/test_daylight_savings.rb +118 -0
  48. data/test/{test_Handler.rb → test_handler.rb} +73 -55
  49. data/test/test_mini_date.rb +32 -0
  50. data/test/test_numerizer.rb +86 -0
  51. data/test/test_parsing.rb +891 -248
  52. data/test/{test_RepeaterDayName.rb → test_repeater_day_name.rb} +16 -17
  53. data/test/test_repeater_day_portion.rb +254 -0
  54. data/test/{test_RepeaterFortnight.rb → test_repeater_fortnight.rb} +17 -18
  55. data/test/{test_RepeaterHour.rb → test_repeater_hour.rb} +23 -20
  56. data/test/test_repeater_minute.rb +34 -0
  57. data/test/{test_RepeaterMonth.rb → test_repeater_month.rb} +21 -18
  58. data/test/{test_RepeaterMonthName.rb → test_repeater_month_name.rb} +18 -19
  59. data/test/test_repeater_season.rb +40 -0
  60. data/test/{test_RepeaterTime.rb → test_repeater_time.rb} +39 -23
  61. data/test/{test_RepeaterWeek.rb → test_repeater_week.rb} +17 -18
  62. data/test/test_repeater_weekday.rb +55 -0
  63. data/test/{test_RepeaterWeekend.rb → test_repeater_weekend.rb} +22 -23
  64. data/test/{test_RepeaterYear.rb → test_repeater_year.rb} +25 -19
  65. data/test/{test_Span.rb → test_span.rb} +7 -8
  66. data/test/{test_Token.rb → test_token.rb} +6 -7
  67. metadata +163 -85
  68. data/History.txt +0 -49
  69. data/Manifest.txt +0 -47
  70. data/README.txt +0 -149
  71. data/lib/chronic/chronic.rb +0 -239
  72. data/lib/numerizer/numerizer.rb +0 -103
  73. data/test/suite.rb +0 -9
  74. data/test/test_Chronic.rb +0 -50
  75. data/test/test_Numerizer.rb +0 -48
  76. data/test/test_Time.rb +0 -50
@@ -1,26 +1,33 @@
1
- #module Chronic
1
+ module Chronic
2
+ class Grabber < Tag
2
3
 
3
- class Chronic::Grabber < Chronic::Tag #:nodoc:
4
- def self.scan(tokens)
5
- tokens.each_index do |i|
6
- if t = self.scan_for_all(tokens[i]) then tokens[i].tag(t); next end
4
+ # Scan an Array of Tokens and apply any necessary Grabber tags to
5
+ # each token.
6
+ #
7
+ # tokens - An Array of Token objects to scan.
8
+ # options - The Hash of options specified in Chronic::parse.
9
+ #
10
+ # Returns an Array of Token objects.
11
+ def self.scan(tokens, options)
12
+ tokens.each do |token|
13
+ if t = scan_for_all(token) then token.tag(t); next end
7
14
  end
8
- tokens
9
15
  end
10
-
16
+
17
+ # token - The Token object to scan.
18
+ #
19
+ # Returns a new Grabber object.
11
20
  def self.scan_for_all(token)
12
- scanner = {/last/ => :last,
13
- /this/ => :this,
14
- /next/ => :next}
15
- scanner.keys.each do |scanner_item|
16
- return self.new(scanner[scanner_item]) if scanner_item =~ token.word
17
- end
18
- return nil
21
+ scan_for token, self,
22
+ {
23
+ /last/ => :last,
24
+ /this/ => :this,
25
+ /next/ => :next
26
+ }
19
27
  end
20
-
28
+
21
29
  def to_s
22
30
  'grabber-' << @type.to_s
23
31
  end
24
32
  end
25
-
26
- #end
33
+ end
@@ -0,0 +1,97 @@
1
+ module Chronic
2
+ class Handler
3
+
4
+ attr_reader :pattern
5
+
6
+ attr_reader :handler_method
7
+
8
+ # pattern - An Array of patterns to match tokens against.
9
+ # handler_method - A Symbol representing the method to be invoked
10
+ # when a pattern matches.
11
+ def initialize(pattern, handler_method)
12
+ @pattern = pattern
13
+ @handler_method = handler_method
14
+ end
15
+
16
+ # tokens - An Array of tokens to process.
17
+ # definitions - A Hash of definitions to check against.
18
+ #
19
+ # Returns true if a match is found.
20
+ def match(tokens, definitions)
21
+ token_index = 0
22
+ @pattern.each do |elements|
23
+ was_optional = false
24
+ elements = [elements] unless elements.is_a?(Array)
25
+
26
+ elements.each_index do |i|
27
+ name = elements[i].to_s
28
+ optional = name[-1, 1] == '?'
29
+ name = name.chop if optional
30
+
31
+ case elements[i]
32
+ when Symbol
33
+ if tags_match?(name, tokens, token_index)
34
+ token_index += 1
35
+ break
36
+ else
37
+ if optional
38
+ was_optional = true
39
+ next
40
+ elsif i + 1 < elements.count
41
+ next
42
+ else
43
+ return false unless was_optional
44
+ end
45
+ end
46
+
47
+ when String
48
+ return true if optional && token_index == tokens.size
49
+
50
+ if definitions.key?(name.to_sym)
51
+ sub_handlers = definitions[name.to_sym]
52
+ else
53
+ raise "Invalid subset #{name} specified"
54
+ end
55
+
56
+ sub_handlers.each do |sub_handler|
57
+ return true if sub_handler.match(tokens[token_index..tokens.size], definitions)
58
+ end
59
+ else
60
+ raise "Invalid match type: #{elements[i].class}"
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ return false if token_index != tokens.size
67
+ return true
68
+ end
69
+
70
+ def invoke(type, tokens, parser, options)
71
+ if Chronic.debug
72
+ puts "-#{type}"
73
+ puts "Handler: #{@handler_method}"
74
+ end
75
+
76
+ parser.send(@handler_method, tokens, options)
77
+ end
78
+
79
+ # other - The other Handler object to compare.
80
+ #
81
+ # Returns true if these Handlers match.
82
+ def ==(other)
83
+ @pattern == other.pattern
84
+ end
85
+
86
+ private
87
+
88
+ def tags_match?(name, tokens, token_index)
89
+ klass = Chronic.const_get(name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase })
90
+
91
+ if tokens[token_index]
92
+ !tokens[token_index].tags.select { |o| o.kind_of?(klass) }.empty?
93
+ end
94
+ end
95
+
96
+ end
97
+ end