chronic 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
File without changes
data/.gitignore CHANGED
@@ -2,3 +2,4 @@ pkg
2
2
  *.rbc
3
3
  rdoc
4
4
  .yardoc
5
+ doc
data/.yardopts CHANGED
@@ -1,3 +1,3 @@
1
1
  -m markdown
2
- --main README.md
2
+ --readme README.md
3
3
  --title "Chronic - Natural language date/time parsing"
data/HISTORY.md CHANGED
@@ -1,3 +1,15 @@
1
+ # 0.4.4
2
+
3
+ * Fix RepeaterYear for fetching past year offsets when the current day is
4
+ later than the last day of the same month in a past year (leap years) ie
5
+ on 29th/feb (leap year) `last year` should (and now does) return 28th/feb
6
+ instead of 1st/march
7
+
8
+ # 0.4.3 / 2011-06-08
9
+
10
+ * Fix issue with parsing 1:xxPM -- Ensure 1 is treated as ambiguous, not
11
+ just >1
12
+
1
13
  # 0.4.2 / 2011-06-07
2
14
 
3
15
  * Fix MonthRepeater for fetching past month offsets when current day is
@@ -3,7 +3,6 @@ LICENSE
3
3
  Manifest.txt
4
4
  README.md
5
5
  Rakefile
6
- benchmark/benchmark.rb
7
6
  chronic.gemspec
8
7
  lib/chronic.rb
9
8
  lib/chronic/chronic.rb
@@ -56,4 +55,4 @@ test/test_RepeaterYear.rb
56
55
  test/test_Span.rb
57
56
  test/test_Time.rb
58
57
  test/test_Token.rb
59
- test/test_parsing.rb
58
+ test/test_parsing.rb
data/README.md CHANGED
@@ -133,8 +133,9 @@ Specific Times (many of the above with an added time)
133
133
 
134
134
  Chronic allows you to set which Time class to use when constructing times. By
135
135
  default, the built in Ruby time class creates times in your system's local
136
- time zone. You can set this to something like ActiveSupport's TimeZone class
137
- to get full time zone support.
136
+ time zone. You can set this to something like ActiveSupport's
137
+ [TimeZone](http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html)
138
+ class to get full time zone support.
138
139
 
139
140
  >> Time.zone = "UTC"
140
141
  >> Chronic.time_class = Time.zone
@@ -28,7 +28,7 @@ require 'date'
28
28
  #
29
29
  # @author Tom Preston-Werner, Lee Jarvis
30
30
  module Chronic
31
- VERSION = "0.4.3"
31
+ VERSION = "0.4.4"
32
32
 
33
33
  class << self
34
34
 
@@ -17,6 +17,8 @@ module Chronic
17
17
  # will be returned (depending on the value of `:guess`). If no
18
18
  # date or time can be found, `nil` will be returned
19
19
  #
20
+ # @param [String] text The text to parse
21
+ #
20
22
  # @option opts [Symbol] :context (:future)
21
23
  # * If your string represents a birthday, you can set `:context` to
22
24
  # `:past` and if an ambiguous string is given, it will assume it is
@@ -57,7 +59,6 @@ module Chronic
57
59
  #
58
60
  # @return [Time, Chronic::Span, nil]
59
61
  def parse(text, opts={})
60
- @text = text
61
62
  options = DEFAULT_OPTIONS.merge opts
62
63
 
63
64
  # ensure the specified options are valid
@@ -102,7 +102,7 @@ module Chronic
102
102
  def handle_sd_rmn_sy(tokens, options) #:nodoc:
103
103
  new_tokens = [tokens[1], tokens[0], tokens[2]]
104
104
  time_tokens = tokens.last(tokens.size - 3)
105
- self.handle_rmn_sd_sy(new_tokens + time_tokens, options)
105
+ handle_rmn_sd_sy(new_tokens + time_tokens, options)
106
106
  end
107
107
 
108
108
  # Handle scalar-month/scalar-day/scalar-year (endian middle)
@@ -125,14 +125,14 @@ module Chronic
125
125
  def handle_sd_sm_sy(tokens, options) #:nodoc:
126
126
  new_tokens = [tokens[1], tokens[0], tokens[2]]
127
127
  time_tokens = tokens.last(tokens.size - 3)
128
- self.handle_sm_sd_sy(new_tokens + time_tokens, options)
128
+ handle_sm_sd_sy(new_tokens + time_tokens, options)
129
129
  end
130
130
 
131
131
  # Handle scalar-year/scalar-month/scalar-day
132
132
  def handle_sy_sm_sd(tokens, options) #:nodoc:
133
133
  new_tokens = [tokens[1], tokens[2], tokens[0]]
134
134
  time_tokens = tokens.last(tokens.size - 3)
135
- self.handle_sm_sd_sy(new_tokens + time_tokens, options)
135
+ handle_sm_sd_sy(new_tokens + time_tokens, options)
136
136
  end
137
137
 
138
138
  # Handle scalar-month/scalar-year
@@ -160,13 +160,13 @@ module Chronic
160
160
  # Handle repeaters
161
161
  def handle_r(tokens, options) #:nodoc:
162
162
  dd_tokens = dealias_and_disambiguate_times(tokens, options)
163
- self.get_anchor(dd_tokens, options)
163
+ get_anchor(dd_tokens, options)
164
164
  end
165
165
 
166
166
  # Handle repeater/grabber/repeater
167
167
  def handle_r_g_r(tokens, options) #:nodoc:
168
168
  new_tokens = [tokens[1], tokens[0], tokens[2]]
169
- self.handle_r(new_tokens, options)
169
+ handle_r(new_tokens, options)
170
170
  end
171
171
 
172
172
  # arrows
@@ -185,19 +185,19 @@ module Chronic
185
185
  repeater = tokens[1].get_tag(Repeater)
186
186
  span = Span.new(Chronic.now, Chronic.now + 1)
187
187
 
188
- self.handle_srp(tokens, span, options)
188
+ handle_srp(tokens, span, options)
189
189
  end
190
190
 
191
191
  # Handle pointer/scalar/repeater
192
192
  def handle_p_s_r(tokens, options) #:nodoc:
193
193
  new_tokens = [tokens[1], tokens[2], tokens[0]]
194
- self.handle_s_r_p(new_tokens, options)
194
+ handle_s_r_p(new_tokens, options)
195
195
  end
196
196
 
197
197
  # Handle scalar/repeater/pointer/anchor
198
198
  def handle_s_r_p_a(tokens, options) #:nodoc:
199
199
  anchor_span = get_anchor(tokens[3..tokens.size - 1], options)
200
- self.handle_srp(tokens, anchor_span, options)
200
+ handle_srp(tokens, anchor_span, options)
201
201
  end
202
202
 
203
203
  # narrows
@@ -247,7 +247,7 @@ module Chronic
247
247
  grabber = Grabber.new(:this)
248
248
  pointer = :future
249
249
 
250
- repeaters = self.get_repeaters(tokens)
250
+ repeaters = get_repeaters(tokens)
251
251
  repeaters.size.times { tokens.pop }
252
252
 
253
253
  if tokens.first && tokens.first.get_tag(Grabber)
@@ -358,18 +358,33 @@ module Chronic
358
358
 
359
359
  end
360
360
 
361
- class Handler #:nodoc:
362
- attr_accessor :pattern, :handler_method
361
+ class Handler
362
+ # @return [Array] A list of patterns
363
+ attr_accessor :pattern
363
364
 
365
+ # @return [Symbol] The method which handles this list of patterns.
366
+ # This method should exist inside the {Handlers} module
367
+ attr_accessor :handler_method
368
+
369
+ # @param [Array] pattern A list of patterns to match tokens against
370
+ # @param [Symbol] handler_method The method to be invoked when patterns
371
+ # are matched. This method should exist inside the {Handlers} module
364
372
  def initialize(pattern, handler_method)
365
373
  @pattern = pattern
366
374
  @handler_method = handler_method
367
375
  end
368
376
 
377
+ # @param [#to_s] The snake_case name representing a Chronic constant
378
+ # @return [Class] The class represented by `name`
379
+ # @raise [NameError] Raises if this constant could not be found
369
380
  def constantize(name)
370
381
  Chronic.const_get name.to_s.gsub(/(^|_)(.)/) { $2.upcase }
371
382
  end
372
383
 
384
+ # @param [Array] tokens
385
+ # @param [Hash] definitions
386
+ # @return [Boolean]
387
+ # @see Chronic.tokens_to_span
373
388
  def match(tokens, definitions)
374
389
  token_index = 0
375
390
  @pattern.each do |element|
@@ -397,8 +412,10 @@ module Chronic
397
412
  return true
398
413
  end
399
414
 
415
+ # @param [Handler] The handler to compare
416
+ # @return [Boolean] True if these handlers match
400
417
  def ==(other)
401
- self.pattern == other.pattern
418
+ @pattern == other.pattern
402
419
  end
403
420
  end
404
421
 
@@ -4,7 +4,6 @@ module Chronic
4
4
 
5
5
  def initialize(type)
6
6
  super
7
- @current_day_start = nil
8
7
  end
9
8
 
10
9
  def next(pointer)
@@ -4,7 +4,6 @@ module Chronic
4
4
 
5
5
  def initialize(type)
6
6
  super
7
- @current_day_start = nil
8
7
  end
9
8
 
10
9
  def next(pointer)
@@ -11,7 +11,6 @@ module Chronic
11
11
 
12
12
  def initialize(type)
13
13
  super
14
- @current_span = nil
15
14
 
16
15
  if type.kind_of? Integer
17
16
  @range = (@type * 60 * 60)..((@type + 12) * 60 * 60)
@@ -4,7 +4,6 @@ module Chronic
4
4
 
5
5
  def initialize(type)
6
6
  super
7
- @current_fortnight_start = nil
8
7
  end
9
8
 
10
9
  def next(pointer)
@@ -4,7 +4,6 @@ module Chronic
4
4
 
5
5
  def initialize(type)
6
6
  super
7
- @current_hour_start = nil
8
7
  end
9
8
 
10
9
  def next(pointer)
@@ -4,7 +4,6 @@ module Chronic
4
4
 
5
5
  def initialize(type)
6
6
  super
7
- @current_minute_start = nil
8
7
  end
9
8
 
10
9
  def next(pointer = :future)
@@ -7,7 +7,6 @@ module Chronic
7
7
 
8
8
  def initialize(type)
9
9
  super
10
- @current_month_start = nil
11
10
  end
12
11
 
13
12
  def next(pointer)
@@ -18,7 +18,6 @@ module Chronic
18
18
 
19
19
  def initialize(type)
20
20
  super
21
- @current_month_begin = nil
22
21
  end
23
22
 
24
23
  def next(pointer)
@@ -1,20 +1,38 @@
1
1
  module Chronic
2
2
  class Season
3
- attr_reader :start, :end
3
+ # @return [MiniDate]
4
+ attr_reader :start
4
5
 
5
- def initialize(myStart, myEnd)
6
- @start = myStart
7
- @end = myEnd
6
+ # @return [MiniDate]
7
+ attr_reader :end
8
+
9
+ # @param [MiniDate] start_date
10
+ # @param [MiniDate] end_date
11
+ def initialize(start_date, end_date)
12
+ @start = start_date
13
+ @end = end_date
8
14
  end
9
15
 
16
+ # @param [Symbol] season The season name
17
+ # @param [Integer] pointer The direction (-1 for past, 1 for future)
18
+ # @return [Symbol] The new season name
10
19
  def self.find_next_season(season, pointer)
11
20
  lookup = {:spring => 0, :summer => 1, :autumn => 2, :winter => 3}
12
- next_season_num = (lookup[season]+1*pointer) % 4
21
+ next_season_num = (lookup[season] + 1 * pointer) % 4
13
22
  lookup.invert[next_season_num]
14
23
  end
15
24
 
16
- def self.season_after(season); find_next_season(season, +1); end
17
- def self.season_before(season); find_next_season(season, -1); end
25
+ # @param [Symbol] season The season name
26
+ # @return [Symbol] The new season name
27
+ def self.season_after(season)
28
+ find_next_season(season, +1)
29
+ end
30
+
31
+ # @param [Symbol] season The season name
32
+ # @return [Symbol] The new season name
33
+ def self.season_before(season)
34
+ find_next_season(season, -1)
35
+ end
18
36
  end
19
37
 
20
38
  class RepeaterSeason < Repeater #:nodoc:
@@ -28,7 +46,6 @@ module Chronic
28
46
 
29
47
  def initialize(type)
30
48
  super
31
- @next_season_start = nil
32
49
  end
33
50
 
34
51
  def next(pointer)
@@ -4,7 +4,6 @@ module Chronic
4
4
 
5
5
  def initialize(type)
6
6
  super
7
- @second_start = nil
8
7
  end
9
8
 
10
9
  def next(pointer = :future)
@@ -27,7 +27,6 @@ module Chronic
27
27
  end
28
28
 
29
29
  def initialize(time)
30
- @current_time = nil
31
30
  t = time.gsub(/\:/, '')
32
31
 
33
32
  @type =
@@ -4,7 +4,6 @@ module Chronic
4
4
 
5
5
  def initialize(type)
6
6
  super
7
- @current_week_start = nil
8
7
  end
9
8
 
10
9
  def next(pointer)
@@ -13,7 +13,6 @@ module Chronic
13
13
 
14
14
  def initialize(type)
15
15
  super
16
- @current_weekday_start = nil
17
16
  end
18
17
 
19
18
  def next(pointer)
@@ -4,7 +4,6 @@ module Chronic
4
4
 
5
5
  def initialize(type)
6
6
  super
7
- @current_week_start = nil
8
7
  end
9
8
 
10
9
  def next(pointer)
@@ -4,7 +4,6 @@ module Chronic
4
4
 
5
5
  def initialize(type)
6
6
  super
7
- @current_year_start = nil
8
7
  end
9
8
 
10
9
  def next(pointer)
@@ -45,13 +44,8 @@ module Chronic
45
44
 
46
45
  def offset(span, amount, pointer)
47
46
  direction = pointer == :future ? 1 : -1
48
-
49
- sb = span.begin
50
- new_begin = Time.construct(sb.year + (amount * direction), sb.month, sb.day, sb.hour, sb.min, sb.sec)
51
-
52
- se = span.end
53
- new_end = Time.construct(se.year + (amount * direction), se.month, se.day, se.hour, se.min, se.sec)
54
-
47
+ new_begin = build_offset_time(span.begin, amount, direction)
48
+ new_end = build_offset_time(span.end, amount, direction)
55
49
  Span.new(new_begin, new_end)
56
50
  end
57
51
 
@@ -62,5 +56,22 @@ module Chronic
62
56
  def to_s
63
57
  super << '-year'
64
58
  end
59
+
60
+ private
61
+
62
+ def build_offset_time(time, amount, direction)
63
+ year = time.year + (amount * direction)
64
+ days = month_days(year, time.month)
65
+ day = time.day > days ? days : time.day
66
+ Time.construct(year, time.month, day, time.hour, time.min, time.sec)
67
+ end
68
+
69
+ def month_days(year, month)
70
+ if Date.leap?(year)
71
+ RepeaterMonth::MONTH_DAYS_LEAP[month - 1]
72
+ else
73
+ RepeaterMonth::MONTH_DAYS[month - 1]
74
+ end
75
+ end
65
76
  end
66
77
  end
@@ -14,7 +14,7 @@ module Chronic
14
14
 
15
15
  # Tag this token with the specified tag
16
16
  #
17
- # @param [Tag] new_tag A instance of {Tag} or one of its subclasses
17
+ # @param [Tag] new_tag An instance of {Tag} or one of its subclasses
18
18
  def tag(new_tag)
19
19
  @tags << new_tag
20
20
  end
@@ -57,6 +57,13 @@ class TestRepeaterYear < Test::Unit::TestCase
57
57
 
58
58
  assert_equal Time.local(1996, 8, 16, 14), offset_span.begin
59
59
  assert_equal Time.local(1996, 8, 16, 14, 0, 1), offset_span.end
60
+
61
+ now = Time.local(2008, 2, 29)
62
+ span = Chronic::Span.new(now, now + 1)
63
+ offset_span = Chronic::RepeaterYear.new(:year).offset(span, 1, :past)
64
+
65
+ assert_equal Time.local(2007, 2, 28), offset_span.begin
66
+ assert_equal Time.local(2007, 2, 28, 0, 0, 1), offset_span.end
60
67
  end
61
68
 
62
69
  end
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chronic
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 4
9
- - 3
10
- version: 0.4.3
4
+ prerelease:
5
+ version: 0.4.4
11
6
  platform: ruby
12
7
  authors:
13
8
  - Tom Preston-Werner
@@ -16,8 +11,7 @@ autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
13
 
19
- date: 2011-06-08 00:00:00 +01:00
20
- default_executable:
14
+ date: 2011-06-12 00:00:00 Z
21
15
  dependencies: []
22
16
 
23
17
  description: Chronic is a natural language date/time parser written in pure Ruby.
@@ -33,6 +27,7 @@ extra_rdoc_files:
33
27
  - HISTORY.md
34
28
  - LICENSE
35
29
  files:
30
+ - .gemtest
36
31
  - .gitignore
37
32
  - .yardopts
38
33
  - HISTORY.md
@@ -40,7 +35,6 @@ files:
40
35
  - Manifest.txt
41
36
  - README.md
42
37
  - Rakefile
43
- - benchmark/benchmark.rb
44
38
  - chronic.gemspec
45
39
  - lib/chronic.rb
46
40
  - lib/chronic/chronic.rb
@@ -94,7 +88,6 @@ files:
94
88
  - test/test_Time.rb
95
89
  - test/test_Token.rb
96
90
  - test/test_parsing.rb
97
- has_rdoc: true
98
91
  homepage: http://github.com/mojombo/chronic
99
92
  licenses: []
100
93
 
@@ -108,23 +101,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
108
101
  requirements:
109
102
  - - ">="
110
103
  - !ruby/object:Gem::Version
111
- hash: 3
112
- segments:
113
- - 0
114
104
  version: "0"
115
105
  required_rubygems_version: !ruby/object:Gem::Requirement
116
106
  none: false
117
107
  requirements:
118
108
  - - ">="
119
109
  - !ruby/object:Gem::Version
120
- hash: 3
121
- segments:
122
- - 0
123
110
  version: "0"
124
111
  requirements: []
125
112
 
126
113
  rubyforge_project: chronic
127
- rubygems_version: 1.3.7
114
+ rubygems_version: 1.8.5
128
115
  signing_key:
129
116
  specification_version: 3
130
117
  summary: Natural language date/time parsing.
@@ -1,13 +0,0 @@
1
- require 'chronic'
2
- require 'benchmark'
3
-
4
- print "jan 3 2010: "
5
- puts Benchmark.measure { Chronic.parse("jan 3 2010") }
6
-
7
- print "7 hours before tomorrow at midnight: "
8
- puts Benchmark.measure { Chronic.parse("7 hours before tomorrow at midnight") }
9
-
10
- # n = 100
11
- # Benchmark.bm(14) do |x|
12
- # x.report("jan 3 2010:") { for i in 1..n; Chronic.parse("jan 3 2010"); end }
13
- # end