chronic 0.7.0 → 0.8.0

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.
data/HISTORY.md CHANGED
@@ -1,5 +1,11 @@
1
- # HEAD
2
-
1
+ # 0.8.0 / 2012-09-16
2
+
3
+ * Support parsing "<ordinal> of this month" (#109)
4
+ * Support parsing ISO 8601 format (#115)
5
+ * Support parsing "on <day>" without a timestamp (#117)
6
+ * Fix time parsing regexp (#125)
7
+ * Support time when parsing dd-mm-yyy <time> (#126)
8
+ * Allow anchor handler to accept any separators (at, on) (#128)
3
9
  * Support parsing EXIF date format (#112)
4
10
  * Start using minitest for testing
5
11
  * Ensure periods are interpreted as colons (#81).
data/lib/chronic.rb CHANGED
@@ -27,7 +27,7 @@ require 'date'
27
27
  # Chronic.parse('may 27th', :guess => false)
28
28
  # #=> Sun May 27 00:00:00 PDT 2007..Mon May 28 00:00:00 PDT 2007
29
29
  module Chronic
30
- VERSION = "0.7.0"
30
+ VERSION = "0.8.0"
31
31
 
32
32
  class << self
33
33
 
@@ -168,11 +168,11 @@ module Chronic
168
168
  ],
169
169
 
170
170
  :date => [
171
- Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :repeater_time, :separator_slash_or_dash?, :time_zone, :scalar_year], :handle_rdn_rmn_sd_t_tz_sy),
171
+ Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :repeater_time, :separator_slash_or_dash?, :time_zone, :scalar_year], :handle_generic),
172
172
  Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day], :handle_rdn_rmn_sd),
173
173
  Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :scalar_year], :handle_rdn_rmn_sd_sy),
174
174
  Handler.new([:repeater_day_name, :repeater_month_name, :ordinal_day], :handle_rdn_rmn_od),
175
- Handler.new([:scalar_year, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_day, :repeater_time, :time_zone], :handle_sy_sm_sd_t_tz),
175
+ Handler.new([:scalar_year, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_day, :repeater_time, :time_zone], :handle_generic),
176
176
  Handler.new([:repeater_month_name, :scalar_day, :scalar_year], :handle_rmn_sd_sy),
177
177
  Handler.new([:repeater_month_name, :ordinal_day, :scalar_year], :handle_rmn_od_sy),
178
178
  Handler.new([:repeater_month_name, :scalar_day, :scalar_year, :separator_at?, 'time?'], :handle_rmn_sd_sy),
@@ -182,21 +182,23 @@ module Chronic
182
182
  Handler.new([:repeater_month_name, :ordinal_day, :separator_at?, 'time?'], :handle_rmn_od),
183
183
  Handler.new([:ordinal_day, :repeater_month_name, :scalar_year, :separator_at?, 'time?'], :handle_od_rmn_sy),
184
184
  Handler.new([:ordinal_day, :repeater_month_name, :separator_at?, 'time?'], :handle_od_rmn),
185
+ Handler.new([:ordinal_day, :grabber?, :repeater_month, :separator_at?, 'time?'], :handle_od_rm),
185
186
  Handler.new([:scalar_year, :repeater_month_name, :ordinal_day], :handle_sy_rmn_od),
186
187
  Handler.new([:repeater_time, :repeater_day_portion?, :separator_on?, :repeater_month_name, :ordinal_day], :handle_rmn_od_on),
187
188
  Handler.new([:repeater_month_name, :scalar_year], :handle_rmn_sy),
188
189
  Handler.new([:scalar_day, :repeater_month_name, :scalar_year, :separator_at?, 'time?'], :handle_sd_rmn_sy),
189
190
  Handler.new([:scalar_day, :repeater_month_name, :separator_at?, 'time?'], :handle_sd_rmn),
190
191
  Handler.new([:scalar_year, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_day, :separator_at?, 'time?'], :handle_sy_sm_sd),
191
- Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day], :handle_sm_sd),
192
192
  Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_year], :handle_sm_sy),
193
- Handler.new([:scalar_day, :separator_slash_or_dash, :repeater_month_name, :separator_slash_or_dash, :scalar_year], :handle_sm_rmn_sy)
193
+ Handler.new([:scalar_day, :separator_slash_or_dash, :repeater_month_name, :separator_slash_or_dash, :scalar_year, :repeater_time?], :handle_sm_rmn_sy),
194
+ Handler.new([:scalar_year, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :time_zone], :handle_generic)
195
+
194
196
  ],
195
197
 
196
198
  # tonight at 7pm
197
199
  :anchor => [
198
- Handler.new([:grabber?, :repeater, :separator_at?, :repeater?, :repeater?], :handle_r),
199
- Handler.new([:grabber?, :repeater, :repeater, :separator_at?, :repeater?, :repeater?], :handle_r),
200
+ Handler.new([:separator_on?, :grabber?, :repeater, :separator_at?, :repeater?, :repeater?], :handle_r),
201
+ Handler.new([:grabber?, :repeater, :repeater, :separator?, :repeater?, :repeater?], :handle_r),
200
202
  Handler.new([:repeater, :grabber, :repeater], :handle_r_g_r)
201
203
  ],
202
204
 
@@ -204,7 +206,7 @@ module Chronic
204
206
  :arrow => [
205
207
  Handler.new([:scalar, :repeater, :pointer], :handle_s_r_p),
206
208
  Handler.new([:pointer, :scalar, :repeater], :handle_p_s_r),
207
- Handler.new([:scalar, :repeater, :pointer, 'anchor'], :handle_s_r_p_a)
209
+ Handler.new([:scalar, :repeater, :pointer, :separator_at?, 'anchor'], :handle_s_r_p_a)
208
210
  ],
209
211
 
210
212
  # 3rd week in march
@@ -216,6 +218,8 @@ module Chronic
216
218
 
217
219
  endians = [
218
220
  Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day, :separator_slash_or_dash, :scalar_year, :separator_at?, 'time?'], :handle_sm_sd_sy),
221
+ Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day, :separator_at?, 'time?'], :handle_sm_sd),
222
+ Handler.new([:scalar_day, :separator_slash_or_dash, :scalar_month, :separator_at?, 'time?'], :handle_sd_sm),
219
223
  Handler.new([:scalar_day, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_year, :separator_at?, 'time?'], :handle_sd_sm_sy)
220
224
  ]
221
225
 
@@ -49,6 +49,13 @@ module Chronic
49
49
  handle_m_d(month, day, tokens[2..tokens.size], options)
50
50
  end
51
51
 
52
+ # Handle ordinal this month
53
+ def handle_od_rm(tokens, options)
54
+ day = tokens[0].get_tag(OrdinalDay).type
55
+ month = tokens[2].get_tag(RepeaterMonth)
56
+ handle_m_d(month, day, tokens[3..tokens.size], options)
57
+ end
58
+
52
59
  # Handle ordinal-day/repeater-month-name
53
60
  def handle_od_rmn(tokens, options)
54
61
  month = tokens[1].get_tag(RepeaterMonthName)
@@ -124,13 +131,7 @@ module Chronic
124
131
  end
125
132
 
126
133
  # Handle generic timestamp (ruby 1.8)
127
- def handle_rdn_rmn_sd_t_tz_sy(tokens, options)
128
- t = Chronic.time_class.parse(options[:text])
129
- Span.new(t, t + 1)
130
- end
131
-
132
- # Handle generic timestamp (ruby 1.9)
133
- def handle_sy_sm_sd_t_tz(tokens, options)
134
+ def handle_generic(tokens, options)
134
135
  t = Chronic.time_class.parse(options[:text])
135
136
  Span.new(t, t + 1)
136
137
  end
@@ -224,27 +225,30 @@ module Chronic
224
225
  handle_sm_sd_sy(new_tokens + time_tokens, options)
225
226
  end
226
227
 
227
- # Handle scalar-day/scalar-month AND scalar-month/scalar-day
228
+ # Handle scalar-month/scalar-day
228
229
  def handle_sm_sd(tokens, options)
229
230
  month = tokens[0].get_tag(ScalarMonth).type
230
231
  day = tokens[1].get_tag(ScalarDay).type
231
232
  year = Chronic.now.year
232
-
233
- if Array(options[:endian_precedence]).first == :little
234
- day, month = month, day
235
- end
233
+ time_tokens = tokens.last(tokens.size - 2)
236
234
 
237
235
  return if month_overflow?(year, month, day)
238
236
 
239
237
  begin
240
- start_time = Chronic.time_class.local(year, month, day)
241
- end_time = Chronic.time_class.local(year, month, day + 1)
242
- Span.new(start_time, end_time)
238
+ day_start = Chronic.time_class.local(year, month, day)
239
+ day_or_time(day_start, time_tokens, options)
243
240
  rescue ArgumentError
244
241
  nil
245
242
  end
246
243
  end
247
244
 
245
+ # Handle scalar-day/scalar-month
246
+ def handle_sd_sm(tokens, options)
247
+ new_tokens = [tokens[1], tokens[0]]
248
+ time_tokens = tokens.last(tokens.size - 2)
249
+ handle_sm_sd(new_tokens + time_tokens, options)
250
+ end
251
+
248
252
  # Handle scalar-month/scalar-year
249
253
  def handle_sm_sy(tokens, options)
250
254
  month = tokens[0].get_tag(ScalarMonth).type
@@ -321,8 +325,15 @@ module Chronic
321
325
  day = tokens[0].get_tag(ScalarDay).type
322
326
  month = tokens[1].get_tag(RepeaterMonthName).index
323
327
  year = tokens[2].get_tag(ScalarYear).type
324
- time = Chronic.time_class.local(year, month, day)
325
- end_time = Chronic.time_class.local(year, month, day + 1)
328
+ if tokens.size > 3
329
+ time = get_anchor([tokens.last], options).begin
330
+ h, m, s = time.hour, time.min, time.sec
331
+ time = Chronic.time_class.local(year, month, day, h, m, s)
332
+ end_time = Chronic.time_class.local(year, month, day + 1, h, m, s)
333
+ else
334
+ time = Chronic.time_class.local(year, month, day)
335
+ end_time = Chronic.time_class.local(year, month, day + 1)
336
+ end
326
337
  Span.new(time, end_time)
327
338
  end
328
339
 
@@ -420,7 +431,6 @@ module Chronic
420
431
  def get_anchor(tokens, options)
421
432
  grabber = Grabber.new(:this)
422
433
  pointer = :future
423
-
424
434
  repeaters = get_repeaters(tokens)
425
435
  repeaters.size.times { tokens.pop }
426
436
 
@@ -88,7 +88,7 @@ module Chronic
88
88
  #
89
89
  # Returns a new Repeater object.
90
90
  def self.scan_for_times(token)
91
- scan_for token, RepeaterTime, /^\d{1,2}(:?\d{2})?([\.:]?\d{2})?$/
91
+ scan_for token, RepeaterTime, /^\d{1,2}(:?\d{1,2})?([\.:]?\d{1,2})?$/
92
92
  end
93
93
 
94
94
  # token - The Token object we want to scan.
@@ -104,11 +104,11 @@ module Chronic
104
104
  /^weekends?$/ => :weekend,
105
105
  /^(week|business)days?$/ => :weekday,
106
106
  /^days?$/ => :day,
107
- /^hrs?$/ => :hour,
107
+ /^hrs?$/ => :hour,
108
108
  /^hours?$/ => :hour,
109
- /^mins?$/ => :minute,
109
+ /^mins?$/ => :minute,
110
110
  /^minutes?$/ => :minute,
111
- /^secs?$/ => :second,
111
+ /^secs?$/ => :second,
112
112
  /^seconds?$/ => :second
113
113
  }.each do |item, symbol|
114
114
  if item =~ token.word
data/test/test_chronic.rb CHANGED
@@ -67,6 +67,8 @@ class TestChronic < TestCase
67
67
  # middle, little
68
68
  endians = [
69
69
  Chronic::Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day, :separator_slash_or_dash, :scalar_year, :separator_at?, 'time?'], :handle_sm_sd_sy),
70
+ Chronic::Handler.new([:scalar_month, :separator_slash_or_dash, :scalar_day, :separator_at?, 'time?'], :handle_sm_sd),
71
+ Chronic::Handler.new([:scalar_day, :separator_slash_or_dash, :scalar_month, :separator_at?, 'time?'], :handle_sd_sm),
70
72
  Chronic::Handler.new([:scalar_day, :separator_slash_or_dash, :scalar_month, :separator_slash_or_dash, :scalar_year, :separator_at?, 'time?'], :handle_sd_sm_sy)
71
73
  ]
72
74
 
data/test/test_parsing.rb CHANGED
@@ -8,6 +8,14 @@ class TestParsing < TestCase
8
8
  @time_2006_08_16_14_00_00 = TIME_2006_08_16_14_00_00
9
9
  end
10
10
 
11
+ def test_handle_generic
12
+ time = Chronic.parse("2012-08-02T12:00:00+01:00")
13
+ assert_equal Time.local(2012, 8, 2, 12), time
14
+
15
+ time = Chronic.parse("2012-08-02T12:00:00Z")
16
+ assert_equal Time.utc(2012, 8, 2, 12), time
17
+ end
18
+
11
19
  def test_handle_rmn_sd
12
20
  time = parse_now("aug 3")
13
21
  assert_equal Time.local(2006, 8, 3, 12), time
@@ -65,6 +73,11 @@ class TestParsing < TestCase
65
73
  assert_equal Time.local(2007, 5, 27, 5), time
66
74
  end
67
75
 
76
+ def test_handle_od_rm
77
+ time = parse_now("fifteenth of this month")
78
+ assert_equal Time.local(2006, 8, 15, 12), time
79
+ end
80
+
68
81
  def test_handle_od_rmn
69
82
  time = parse_now("22nd February")
70
83
  assert_equal Time.local(2007, 2, 22, 12), time
@@ -294,8 +307,14 @@ class TestParsing < TestCase
294
307
  time = parse_now("05/06", :endian_precedence => [:little, :medium])
295
308
  assert_equal Time.local(2006, 6, 5, 12), time
296
309
 
310
+ time = parse_now("05/06 6:05:57 PM")
311
+ assert_equal Time.local(2006, 5, 6, 18, 05, 57), time
312
+
313
+ time = parse_now("05/06 6:05:57 PM", :endian_precedence => [:little, :medium])
314
+ assert_equal Time.local(2006, 6, 5, 18, 05, 57), time
315
+
297
316
  time = parse_now("13/01")
298
- assert_nil time
317
+ assert_equal Time.local(2006, 1, 13, 12), time
299
318
  end
300
319
 
301
320
  # def test_handle_sm_sy
@@ -310,6 +329,11 @@ class TestParsing < TestCase
310
329
  # end
311
330
 
312
331
  def test_handle_r
332
+ time = parse_now("9am on Saturday")
333
+ assert_equal Time.local(2006, 8, 19, 9), time
334
+
335
+ time = parse_now("on Tuesday")
336
+ assert_equal Time.local(2006, 8, 22, 12), time
313
337
  end
314
338
 
315
339
  def test_handle_r_g_r
@@ -325,6 +349,9 @@ class TestParsing < TestCase
325
349
  end
326
350
 
327
351
  def test_handle_s_r_p_a
352
+ time1 = parse_now("two days ago 0:0:0am")
353
+ time2 = parse_now("two days ago 00:00:00am")
354
+ assert_equal time1, time2
328
355
  end
329
356
 
330
357
  def test_handle_orr
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chronic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-08-01 00:00:00.000000000 Z
13
+ date: 2012-09-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake