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,77 +1,77 @@
1
1
  class Chronic::RepeaterWeekday < Chronic::Repeater #:nodoc:
2
- WEEK_WEEKDAYS = 5
3
- DAY_SECONDS = 86400 # (24 * 60 * 60)
4
-
5
- def initialize(type)
6
- super
7
- @current_weekday_start = nil
8
- end
9
-
10
- def next(pointer)
11
- super
12
-
13
- direction = pointer == :future ? 1 : -1
14
-
15
- if !@current_weekday_start
16
- @current_weekday_start = Time.construct(@now.year, @now.month, @now.day)
17
- @current_weekday_start += direction * DAY_SECONDS
18
-
19
- until is_weekday?(@current_weekday_start.wday)
20
- @current_weekday_start += direction * DAY_SECONDS
21
- end
22
- else
23
- loop do
24
- @current_weekday_start += direction * DAY_SECONDS
25
- break if is_weekday?(@current_weekday_start.wday)
26
- end
27
- end
28
-
29
- Chronic::Span.new(@current_weekday_start, @current_weekday_start + DAY_SECONDS)
30
- end
31
-
32
- def this(pointer = :future)
33
- super
34
-
35
- case pointer
36
- when :past
37
- self.next(:past)
38
- when :future, :none
39
- self.next(:future)
40
- end
41
- end
42
-
43
- def offset(span, amount, pointer)
44
- direction = pointer == :future ? 1 : -1
45
-
46
- num_weekdays_passed = 0; offset = 0
47
- until num_weekdays_passed == amount
48
- offset += direction * DAY_SECONDS
49
- num_weekdays_passed += 1 if is_weekday?((span.begin+offset).wday)
50
- end
51
-
52
- span + offset
53
- end
54
-
55
- def width
56
- DAY_SECONDS
57
- end
58
-
59
- def to_s
60
- super << '-weekday'
61
- end
62
-
63
- private
64
-
65
- def is_weekend?(day)
66
- day == symbol_to_number(:saturday) || day == symbol_to_number(:sunday)
67
- end
68
-
69
- def is_weekday?(day)
70
- !is_weekend?(day)
71
- end
72
-
73
- def symbol_to_number(sym)
74
- lookup = {:sunday => 0, :monday => 1, :tuesday => 2, :wednesday => 3, :thursday => 4, :friday => 5, :saturday => 6}
75
- lookup[sym] || raise("Invalid symbol specified")
76
- end
77
- end
2
+ WEEK_WEEKDAYS = 5
3
+ DAY_SECONDS = 86400 # (24 * 60 * 60)
4
+
5
+ def initialize(type)
6
+ super
7
+ @current_weekday_start = nil
8
+ end
9
+
10
+ def next(pointer)
11
+ super
12
+
13
+ direction = pointer == :future ? 1 : -1
14
+
15
+ if !@current_weekday_start
16
+ @current_weekday_start = Time.construct(@now.year, @now.month, @now.day)
17
+ @current_weekday_start += direction * DAY_SECONDS
18
+
19
+ until is_weekday?(@current_weekday_start.wday)
20
+ @current_weekday_start += direction * DAY_SECONDS
21
+ end
22
+ else
23
+ loop do
24
+ @current_weekday_start += direction * DAY_SECONDS
25
+ break if is_weekday?(@current_weekday_start.wday)
26
+ end
27
+ end
28
+
29
+ Chronic::Span.new(@current_weekday_start, @current_weekday_start + DAY_SECONDS)
30
+ end
31
+
32
+ def this(pointer = :future)
33
+ super
34
+
35
+ case pointer
36
+ when :past
37
+ self.next(:past)
38
+ when :future, :none
39
+ self.next(:future)
40
+ end
41
+ end
42
+
43
+ def offset(span, amount, pointer)
44
+ direction = pointer == :future ? 1 : -1
45
+
46
+ num_weekdays_passed = 0; offset = 0
47
+ until num_weekdays_passed == amount
48
+ offset += direction * DAY_SECONDS
49
+ num_weekdays_passed += 1 if is_weekday?((span.begin+offset).wday)
50
+ end
51
+
52
+ span + offset
53
+ end
54
+
55
+ def width
56
+ DAY_SECONDS
57
+ end
58
+
59
+ def to_s
60
+ super << '-weekday'
61
+ end
62
+
63
+ private
64
+
65
+ def is_weekend?(day)
66
+ day == symbol_to_number(:saturday) || day == symbol_to_number(:sunday)
67
+ end
68
+
69
+ def is_weekday?(day)
70
+ !is_weekend?(day)
71
+ end
72
+
73
+ def symbol_to_number(sym)
74
+ lookup = {:sunday => 0, :monday => 1, :tuesday => 2, :wednesday => 3, :thursday => 4, :friday => 5, :saturday => 6}
75
+ lookup[sym] || raise("Invalid symbol specified")
76
+ end
77
+ end
@@ -1,65 +1,65 @@
1
1
  class Chronic::RepeaterWeekend < Chronic::Repeater #:nodoc:
2
- WEEKEND_SECONDS = 172_800 # (2 * 24 * 60 * 60)
2
+ WEEKEND_SECONDS = 172_800 # (2 * 24 * 60 * 60)
3
3
 
4
- def initialize(type)
5
- super
6
- @current_week_start = nil
7
- end
8
-
9
- def next(pointer)
10
- super
11
-
12
- if !@current_week_start
13
- case pointer
14
- when :future
15
- saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
16
- saturday_repeater.start = @now
17
- next_saturday_span = saturday_repeater.next(:future)
18
- @current_week_start = next_saturday_span.begin
19
- when :past
20
- saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
21
- saturday_repeater.start = (@now + Chronic::RepeaterDay::DAY_SECONDS)
22
- last_saturday_span = saturday_repeater.next(:past)
23
- @current_week_start = last_saturday_span.begin
24
- end
25
- else
26
- direction = pointer == :future ? 1 : -1
27
- @current_week_start += direction * Chronic::RepeaterWeek::WEEK_SECONDS
28
- end
29
-
30
- Chronic::Span.new(@current_week_start, @current_week_start + WEEKEND_SECONDS)
31
- end
32
-
33
- def this(pointer = :future)
34
- super
35
-
36
- case pointer
37
- when :future, :none
38
- saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
39
- saturday_repeater.start = @now
40
- this_saturday_span = saturday_repeater.this(:future)
41
- Chronic::Span.new(this_saturday_span.begin, this_saturday_span.begin + WEEKEND_SECONDS)
42
- when :past
43
- saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
44
- saturday_repeater.start = @now
45
- last_saturday_span = saturday_repeater.this(:past)
46
- Chronic::Span.new(last_saturday_span.begin, last_saturday_span.begin + WEEKEND_SECONDS)
47
- end
48
- end
49
-
50
- def offset(span, amount, pointer)
51
- direction = pointer == :future ? 1 : -1
52
- weekend = Chronic::RepeaterWeekend.new(:weekend)
53
- weekend.start = span.begin
54
- start = weekend.next(pointer).begin + (amount - 1) * direction * Chronic::RepeaterWeek::WEEK_SECONDS
55
- Chronic::Span.new(start, start + (span.end - span.begin))
56
- end
57
-
58
- def width
59
- WEEKEND_SECONDS
60
- end
61
-
62
- def to_s
63
- super << '-weekend'
64
- end
65
- end
4
+ def initialize(type)
5
+ super
6
+ @current_week_start = nil
7
+ end
8
+
9
+ def next(pointer)
10
+ super
11
+
12
+ if !@current_week_start
13
+ case pointer
14
+ when :future
15
+ saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
16
+ saturday_repeater.start = @now
17
+ next_saturday_span = saturday_repeater.next(:future)
18
+ @current_week_start = next_saturday_span.begin
19
+ when :past
20
+ saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
21
+ saturday_repeater.start = (@now + Chronic::RepeaterDay::DAY_SECONDS)
22
+ last_saturday_span = saturday_repeater.next(:past)
23
+ @current_week_start = last_saturday_span.begin
24
+ end
25
+ else
26
+ direction = pointer == :future ? 1 : -1
27
+ @current_week_start += direction * Chronic::RepeaterWeek::WEEK_SECONDS
28
+ end
29
+
30
+ Chronic::Span.new(@current_week_start, @current_week_start + WEEKEND_SECONDS)
31
+ end
32
+
33
+ def this(pointer = :future)
34
+ super
35
+
36
+ case pointer
37
+ when :future, :none
38
+ saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
39
+ saturday_repeater.start = @now
40
+ this_saturday_span = saturday_repeater.this(:future)
41
+ Chronic::Span.new(this_saturday_span.begin, this_saturday_span.begin + WEEKEND_SECONDS)
42
+ when :past
43
+ saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
44
+ saturday_repeater.start = @now
45
+ last_saturday_span = saturday_repeater.this(:past)
46
+ Chronic::Span.new(last_saturday_span.begin, last_saturday_span.begin + WEEKEND_SECONDS)
47
+ end
48
+ end
49
+
50
+ def offset(span, amount, pointer)
51
+ direction = pointer == :future ? 1 : -1
52
+ weekend = Chronic::RepeaterWeekend.new(:weekend)
53
+ weekend.start = span.begin
54
+ start = weekend.next(pointer).begin + (amount - 1) * direction * Chronic::RepeaterWeek::WEEK_SECONDS
55
+ Chronic::Span.new(start, start + (span.end - span.begin))
56
+ end
57
+
58
+ def width
59
+ WEEKEND_SECONDS
60
+ end
61
+
62
+ def to_s
63
+ super << '-weekend'
64
+ end
65
+ end
@@ -1,64 +1,64 @@
1
1
  class Chronic::RepeaterYear < Chronic::Repeater #:nodoc:
2
- YEAR_SECONDS = 31536000 # 365 * 24 * 60 * 60
3
-
4
- def initialize(type)
5
- super
6
- @current_year_start = nil
7
- end
8
-
9
- def next(pointer)
10
- super
11
-
12
- if !@current_year_start
13
- case pointer
14
- when :future
15
- @current_year_start = Time.construct(@now.year + 1)
16
- when :past
17
- @current_year_start = Time.construct(@now.year - 1)
18
- end
19
- else
20
- diff = pointer == :future ? 1 : -1
21
- @current_year_start = Time.construct(@current_year_start.year + diff)
22
- end
23
-
24
- Chronic::Span.new(@current_year_start, Time.construct(@current_year_start.year + 1))
25
- end
26
-
27
- def this(pointer = :future)
28
- super
29
-
30
- case pointer
31
- when :future
32
- this_year_start = Time.construct(@now.year, @now.month, @now.day) + Chronic::RepeaterDay::DAY_SECONDS
33
- this_year_end = Time.construct(@now.year + 1, 1, 1)
34
- when :past
35
- this_year_start = Time.construct(@now.year, 1, 1)
36
- this_year_end = Time.construct(@now.year, @now.month, @now.day)
37
- when :none
38
- this_year_start = Time.construct(@now.year, 1, 1)
39
- this_year_end = Time.construct(@now.year + 1, 1, 1)
40
- end
41
-
42
- Chronic::Span.new(this_year_start, this_year_end)
43
- end
44
-
45
- def offset(span, amount, pointer)
46
- direction = pointer == :future ? 1 : -1
47
-
48
- sb = span.begin
49
- new_begin = Time.construct(sb.year + (amount * direction), sb.month, sb.day, sb.hour, sb.min, sb.sec)
50
-
51
- se = span.end
52
- new_end = Time.construct(se.year + (amount * direction), se.month, se.day, se.hour, se.min, se.sec)
53
-
54
- Chronic::Span.new(new_begin, new_end)
55
- end
56
-
57
- def width
58
- (365 * 24 * 60 * 60)
59
- end
60
-
61
- def to_s
62
- super << '-year'
63
- end
64
- end
2
+ YEAR_SECONDS = 31536000 # 365 * 24 * 60 * 60
3
+
4
+ def initialize(type)
5
+ super
6
+ @current_year_start = nil
7
+ end
8
+
9
+ def next(pointer)
10
+ super
11
+
12
+ if !@current_year_start
13
+ case pointer
14
+ when :future
15
+ @current_year_start = Time.construct(@now.year + 1)
16
+ when :past
17
+ @current_year_start = Time.construct(@now.year - 1)
18
+ end
19
+ else
20
+ diff = pointer == :future ? 1 : -1
21
+ @current_year_start = Time.construct(@current_year_start.year + diff)
22
+ end
23
+
24
+ Chronic::Span.new(@current_year_start, Time.construct(@current_year_start.year + 1))
25
+ end
26
+
27
+ def this(pointer = :future)
28
+ super
29
+
30
+ case pointer
31
+ when :future
32
+ this_year_start = Time.construct(@now.year, @now.month, @now.day) + Chronic::RepeaterDay::DAY_SECONDS
33
+ this_year_end = Time.construct(@now.year + 1, 1, 1)
34
+ when :past
35
+ this_year_start = Time.construct(@now.year, 1, 1)
36
+ this_year_end = Time.construct(@now.year, @now.month, @now.day)
37
+ when :none
38
+ this_year_start = Time.construct(@now.year, 1, 1)
39
+ this_year_end = Time.construct(@now.year + 1, 1, 1)
40
+ end
41
+
42
+ Chronic::Span.new(this_year_start, this_year_end)
43
+ end
44
+
45
+ def offset(span, amount, pointer)
46
+ direction = pointer == :future ? 1 : -1
47
+
48
+ sb = span.begin
49
+ new_begin = Time.construct(sb.year + (amount * direction), sb.month, sb.day, sb.hour, sb.min, sb.sec)
50
+
51
+ se = span.end
52
+ new_end = Time.construct(se.year + (amount * direction), se.month, se.day, se.hour, se.min, se.sec)
53
+
54
+ Chronic::Span.new(new_begin, new_end)
55
+ end
56
+
57
+ def width
58
+ (365 * 24 * 60 * 60)
59
+ end
60
+
61
+ def to_s
62
+ super << '-year'
63
+ end
64
+ end
@@ -1,76 +1,95 @@
1
1
  module Chronic
2
2
 
3
- class Scalar < Tag #:nodoc:
4
- def self.scan(tokens)
5
- # for each token
6
- tokens.each_index do |i|
7
- if t = self.scan_for_scalars(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end
8
- if t = self.scan_for_days(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end
9
- if t = self.scan_for_months(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end
10
- if t = self.scan_for_years(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end
11
- end
12
- tokens
13
- end
3
+ class Scalar < Tag #:nodoc:
4
+ def self.scan(tokens)
5
+ # for each token
6
+ tokens.each_index do |i|
7
+ if t = self.scan_for_scalars(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end
8
+ if t = self.scan_for_days(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end
9
+ if t = self.scan_for_months(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end
10
+ if t = self.scan_for_years(tokens[i], tokens[i + 1]) then tokens[i].tag(t) end
11
+ end
12
+ tokens
13
+ end
14
+
15
+ def self.scan_for_scalars(token, post_token)
16
+ if token.word =~ /^\d*$/
17
+ unless post_token && %w{am pm morning afternoon evening night}.include?(post_token)
18
+ return Scalar.new(token.word.to_i)
19
+ end
20
+ end
21
+ return nil
22
+ end
23
+
24
+ def self.scan_for_days(token, post_token)
25
+ if token.word =~ /^\d\d?$/
26
+ toi = token.word.to_i
27
+ unless toi > 31 || toi < 1 || (post_token && %w{am pm morning afternoon evening night}.include?(post_token.word))
28
+ return ScalarDay.new(toi)
29
+ end
30
+ end
31
+ return nil
32
+ end
33
+
34
+ def self.scan_for_months(token, post_token)
35
+ if token.word =~ /^\d\d?$/
36
+ toi = token.word.to_i
37
+ unless toi > 12 || toi < 1 || (post_token && %w{am pm morning afternoon evening night}.include?(post_token.word))
38
+ return ScalarMonth.new(toi)
39
+ end
40
+ end
41
+ return nil
42
+ end
43
+
44
+ def self.scan_for_years(token, post_token)
45
+ if token.word =~ /^([1-9]\d)?\d\d?$/
46
+ unless post_token && %w{am pm morning afternoon evening night}.include?(post_token.word)
47
+ # Ruby 1.9.2 accepts 2 digit years so we need to guess
48
+ # Of course, this means there is no way to enter a date
49
+ # that happened before 100. Probably an OK tradeoff
50
+ # as it didn't work before, either.
51
+ year = token.word.to_i
52
+ if year < 100
53
+ this_year = Chronic.time_class.now.year
54
+ suffix = this_year.to_s.slice(-2,2).to_i
55
+ year = this_year + (year - suffix)
14
56
 
15
- def self.scan_for_scalars(token, post_token)
16
- if token.word =~ /^\d*$/ || token.word =~ /^\d\.\d*$/
17
- unless post_token && %w{am pm morning afternoon evening night}.include?(post_token)
18
- return Scalar.new(token.word.to_f)
19
- end
20
- end
21
- return nil
22
- end
57
+ # We could just split 50/50 to decide if the user
58
+ # meant the future, however, a user is more likely
59
+ # going to use a 2 digit number while looking back
60
+ # unless in the near future. Splitting the difference
61
+ # at 80/20, however, this could probably be even
62
+ # more conservative (90/10 even)
63
+ year -= 100 if (year - this_year).to_i >= 20
64
+ end
23
65
 
24
- def self.scan_for_days(token, post_token)
25
- if token.word =~ /^\d\d?$/
26
- toi = token.word.to_i
27
- unless toi > 31 || toi < 1 || (post_token && %w{am pm morning afternoon evening night}.include?(post_token.word))
28
- return ScalarDay.new(toi)
29
- end
30
- end
31
- return nil
32
- end
33
-
34
- def self.scan_for_months(token, post_token)
35
- if token.word =~ /^\d\d?$/
36
- toi = token.word.to_i
37
- unless toi > 12 || toi < 1 || (post_token && %w{am pm morning afternoon evening night}.include?(post_token.word))
38
- return ScalarMonth.new(toi)
39
- end
40
- end
41
- return nil
42
- end
43
-
44
- def self.scan_for_years(token, post_token)
45
- if token.word =~ /^([1-9]\d)?\d\d?$/
46
- unless post_token && %w{am pm morning afternoon evening night}.include?(post_token.word)
47
- return ScalarYear.new(token.word.to_i)
48
- end
49
- end
50
- return nil
51
- end
52
-
53
- def to_s
54
- 'scalar'
55
- end
56
- end
57
-
58
- class ScalarDay < Scalar #:nodoc:
59
- def to_s
60
- super << '-day-' << @type.to_s
61
- end
62
- end
63
-
64
- class ScalarMonth < Scalar #:nodoc:
65
- def to_s
66
- super << '-month-' << @type.to_s
67
- end
68
- end
69
-
70
- class ScalarYear < Scalar #:nodoc:
71
- def to_s
72
- super << '-year-' << @type.to_s
73
- end
74
- end
66
+ return ScalarYear.new(year)
67
+ end
68
+ end
69
+ return nil
70
+ end
71
+
72
+ def to_s
73
+ 'scalar'
74
+ end
75
+ end
76
+
77
+ class ScalarDay < Scalar #:nodoc:
78
+ def to_s
79
+ super << '-day-' << @type.to_s
80
+ end
81
+ end
82
+
83
+ class ScalarMonth < Scalar #:nodoc:
84
+ def to_s
85
+ super << '-month-' << @type.to_s
86
+ end
87
+ end
88
+
89
+ class ScalarYear < Scalar #:nodoc:
90
+ def to_s
91
+ super << '-year-' << @type.to_s
92
+ end
93
+ end
75
94
 
76
95
  end