chronic 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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