chronic-mmlac 0.6.4.2 → 0.10.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -3
  3. data/.travis.yml +8 -0
  4. data/HISTORY.md +69 -0
  5. data/README.md +47 -42
  6. data/Rakefile +28 -8
  7. data/chronic.gemspec +9 -3
  8. data/lib/chronic.rb +113 -74
  9. data/lib/chronic/date.rb +82 -0
  10. data/lib/chronic/grabber.rb +9 -7
  11. data/lib/chronic/handler.rb +47 -40
  12. data/lib/chronic/handlers.rb +210 -28
  13. data/lib/chronic/numerizer.rb +11 -2
  14. data/lib/chronic/ordinal.rb +28 -23
  15. data/lib/chronic/parser.rb +268 -0
  16. data/lib/chronic/pointer.rb +9 -7
  17. data/lib/chronic/repeater.rb +58 -48
  18. data/lib/chronic/repeaters/repeater_day.rb +4 -3
  19. data/lib/chronic/repeaters/repeater_day_name.rb +5 -4
  20. data/lib/chronic/repeaters/repeater_day_portion.rb +29 -14
  21. data/lib/chronic/repeaters/repeater_fortnight.rb +4 -3
  22. data/lib/chronic/repeaters/repeater_hour.rb +4 -3
  23. data/lib/chronic/repeaters/repeater_minute.rb +4 -3
  24. data/lib/chronic/repeaters/repeater_month.rb +5 -4
  25. data/lib/chronic/repeaters/repeater_month_name.rb +4 -3
  26. data/lib/chronic/repeaters/repeater_season.rb +5 -3
  27. data/lib/chronic/repeaters/repeater_second.rb +4 -3
  28. data/lib/chronic/repeaters/repeater_time.rb +35 -25
  29. data/lib/chronic/repeaters/repeater_week.rb +4 -3
  30. data/lib/chronic/repeaters/repeater_weekday.rb +4 -3
  31. data/lib/chronic/repeaters/repeater_weekend.rb +4 -3
  32. data/lib/chronic/repeaters/repeater_year.rb +5 -4
  33. data/lib/chronic/scalar.rb +40 -68
  34. data/lib/chronic/season.rb +1 -12
  35. data/lib/chronic/separator.rb +142 -23
  36. data/lib/chronic/sign.rb +49 -0
  37. data/lib/chronic/span.rb +2 -2
  38. data/lib/chronic/tag.rb +10 -15
  39. data/lib/chronic/time.rb +40 -0
  40. data/lib/chronic/time_zone.rb +9 -7
  41. data/lib/chronic/token.rb +16 -10
  42. data/test/helper.rb +7 -1
  43. data/test/{test_Chronic.rb → test_chronic.rb} +69 -34
  44. data/test/{test_DaylightSavings.rb → test_daylight_savings.rb} +1 -1
  45. data/test/{test_Handler.rb → test_handler.rb} +38 -14
  46. data/test/{test_MiniDate.rb → test_mini_date.rb} +9 -9
  47. data/test/{test_Numerizer.rb → test_numerizer.rb} +16 -2
  48. data/test/test_parsing.rb +367 -18
  49. data/test/{test_RepeaterDayName.rb → test_repeater_day_name.rb} +1 -1
  50. data/test/test_repeater_day_portion.rb +254 -0
  51. data/test/{test_RepeaterFortnight.rb → test_repeater_fortnight.rb} +1 -1
  52. data/test/{test_RepeaterHour.rb → test_repeater_hour.rb} +1 -1
  53. data/test/{test_RepeaterMinute.rb → test_repeater_minute.rb} +1 -1
  54. data/test/{test_RepeaterMonth.rb → test_repeater_month.rb} +1 -1
  55. data/test/{test_RepeaterMonthName.rb → test_repeater_month_name.rb} +1 -1
  56. data/test/{test_RepeaterSeason.rb → test_repeater_season.rb} +1 -1
  57. data/test/{test_RepeaterTime.rb → test_repeater_time.rb} +19 -1
  58. data/test/{test_RepeaterWeek.rb → test_repeater_week.rb} +1 -1
  59. data/test/{test_RepeaterWeekday.rb → test_repeater_weekday.rb} +1 -1
  60. data/test/{test_RepeaterWeekend.rb → test_repeater_weekend.rb} +1 -1
  61. data/test/{test_RepeaterYear.rb → test_repeater_year.rb} +1 -1
  62. data/test/{test_Span.rb → test_span.rb} +2 -2
  63. data/test/{test_Token.rb → test_token.rb} +1 -1
  64. metadata +107 -46
  65. data/.gemtest +0 -0
  66. data/.yardopts +0 -3
  67. data/lib/chronic/chronic.rb +0 -325
@@ -2,14 +2,15 @@ module Chronic
2
2
  class RepeaterDay < Repeater #:nodoc:
3
3
  DAY_SECONDS = 86_400 # (24 * 60 * 60)
4
4
 
5
- def initialize(type)
5
+ def initialize(type, options = {})
6
6
  super
7
+ @current_day_start = nil
7
8
  end
8
9
 
9
10
  def next(pointer)
10
11
  super
11
12
 
12
- if !@current_day_start
13
+ unless @current_day_start
13
14
  @current_day_start = Chronic.time_class.local(@now.year, @now.month, @now.day)
14
15
  end
15
16
 
@@ -50,4 +51,4 @@ module Chronic
50
51
  super << '-day'
51
52
  end
52
53
  end
53
- end
54
+ end
@@ -2,8 +2,9 @@ module Chronic
2
2
  class RepeaterDayName < Repeater #:nodoc:
3
3
  DAY_SECONDS = 86400 # (24 * 60 * 60)
4
4
 
5
- def initialize(type)
5
+ def initialize(type, options = {})
6
6
  super
7
+ @current_date = nil
7
8
  end
8
9
 
9
10
  def next(pointer)
@@ -11,8 +12,8 @@ module Chronic
11
12
 
12
13
  direction = pointer == :future ? 1 : -1
13
14
 
14
- if !@current_date
15
- @current_date = Date.new(@now.year, @now.month, @now.day)
15
+ unless @current_date
16
+ @current_date = ::Date.new(@now.year, @now.month, @now.day)
16
17
  @current_date += direction
17
18
 
18
19
  day_num = symbol_to_number(@type)
@@ -49,4 +50,4 @@ module Chronic
49
50
  lookup[sym] || raise("Invalid symbol specified")
50
51
  end
51
52
  end
52
- end
53
+ end
@@ -9,8 +9,9 @@ module Chronic
9
9
  :night => (20 * 60 * 60)..(24 * 60 * 60), # 8pm-12pm
10
10
  }
11
11
 
12
- def initialize(type)
12
+ def initialize(type, options = {})
13
13
  super
14
+ @current_span = nil
14
15
 
15
16
  if type.kind_of? Integer
16
17
  @range = (@type * 60 * 60)..((@type + 12) * 60 * 60)
@@ -25,41 +26,45 @@ module Chronic
25
26
  def next(pointer)
26
27
  super
27
28
 
28
- full_day = 60 * 60 * 24
29
-
30
- if !@current_span
29
+ unless @current_span
31
30
  now_seconds = @now - Chronic.construct(@now.year, @now.month, @now.day)
32
31
  if now_seconds < @range.begin
33
32
  case pointer
34
33
  when :future
35
34
  range_start = Chronic.construct(@now.year, @now.month, @now.day) + @range.begin
36
35
  when :past
37
- range_start = Chronic.construct(@now.year, @now.month, @now.day) - full_day + @range.begin
36
+ range_start = Chronic.construct(@now.year, @now.month, @now.day - 1) + @range.begin
38
37
  end
39
38
  elsif now_seconds > @range.end
40
39
  case pointer
41
40
  when :future
42
- range_start = Chronic.construct(@now.year, @now.month, @now.day) + full_day + @range.begin
41
+ range_start = Chronic.construct(@now.year, @now.month, @now.day + 1) + @range.begin
43
42
  when :past
44
43
  range_start = Chronic.construct(@now.year, @now.month, @now.day) + @range.begin
45
44
  end
46
45
  else
47
46
  case pointer
48
47
  when :future
49
- range_start = Chronic.construct(@now.year, @now.month, @now.day) + full_day + @range.begin
48
+ range_start = Chronic.construct(@now.year, @now.month, @now.day + 1) + @range.begin
50
49
  when :past
51
- range_start = Chronic.construct(@now.year, @now.month, @now.day) - full_day + @range.begin
50
+ range_start = Chronic.construct(@now.year, @now.month, @now.day - 1) + @range.begin
52
51
  end
53
52
  end
54
-
55
- @current_span = Span.new(range_start, range_start + (@range.end - @range.begin))
53
+ offset = (@range.end - @range.begin)
54
+ range_end = construct_date_from_reference_and_offset(range_start, offset)
55
+ @current_span = Span.new(range_start, range_end)
56
56
  else
57
+ days_to_shift_window =
57
58
  case pointer
58
59
  when :future
59
- @current_span += full_day
60
+ 1
60
61
  when :past
61
- @current_span -= full_day
62
+ -1
62
63
  end
64
+
65
+ new_begin = Chronic.construct(@current_span.begin.year, @current_span.begin.month, @current_span.begin.day + days_to_shift_window, @current_span.begin.hour, @current_span.begin.min, @current_span.begin.sec)
66
+ new_end = Chronic.construct(@current_span.end.year, @current_span.end.month, @current_span.end.day + days_to_shift_window, @current_span.end.hour, @current_span.end.min, @current_span.end.sec)
67
+ @current_span = Span.new(new_begin, new_end)
63
68
  end
64
69
  end
65
70
 
@@ -67,7 +72,8 @@ module Chronic
67
72
  super
68
73
 
69
74
  range_start = Chronic.construct(@now.year, @now.month, @now.day) + @range.begin
70
- @current_span = Span.new(range_start, range_start + (@range.end - @range.begin))
75
+ range_end = construct_date_from_reference_and_offset(range_start)
76
+ @current_span = Span.new(range_start, range_end)
71
77
  end
72
78
 
73
79
  def offset(span, amount, pointer)
@@ -90,5 +96,14 @@ module Chronic
90
96
  def to_s
91
97
  super << '-dayportion-' << @type.to_s
92
98
  end
99
+
100
+ private
101
+ def construct_date_from_reference_and_offset(reference, offset = nil)
102
+ elapsed_seconds_for_range = offset || (@range.end - @range.begin)
103
+ second_hand = ((elapsed_seconds_for_range - (12 * 60))) % 60
104
+ minute_hand = (elapsed_seconds_for_range - second_hand) / (60) % 60
105
+ hour_hand = (elapsed_seconds_for_range - minute_hand - second_hand) / (60 * 60) + reference.hour % 24
106
+ Chronic.construct(reference.year, reference.month, reference.day, hour_hand, minute_hand, second_hand)
107
+ end
93
108
  end
94
- end
109
+ end
@@ -2,14 +2,15 @@ module Chronic
2
2
  class RepeaterFortnight < Repeater #:nodoc:
3
3
  FORTNIGHT_SECONDS = 1_209_600 # (14 * 24 * 60 * 60)
4
4
 
5
- def initialize(type)
5
+ def initialize(type, options = {})
6
6
  super
7
+ @current_fortnight_start = nil
7
8
  end
8
9
 
9
10
  def next(pointer)
10
11
  super
11
12
 
12
- if !@current_fortnight_start
13
+ unless @current_fortnight_start
13
14
  case pointer
14
15
  when :future
15
16
  sunday_repeater = RepeaterDayName.new(:sunday)
@@ -68,4 +69,4 @@ module Chronic
68
69
  super << '-fortnight'
69
70
  end
70
71
  end
71
- end
72
+ end
@@ -2,14 +2,15 @@ module Chronic
2
2
  class RepeaterHour < Repeater #:nodoc:
3
3
  HOUR_SECONDS = 3600 # 60 * 60
4
4
 
5
- def initialize(type)
5
+ def initialize(type, options = {})
6
6
  super
7
+ @current_hour_start = nil
7
8
  end
8
9
 
9
10
  def next(pointer)
10
11
  super
11
12
 
12
- if !@current_hour_start
13
+ unless @current_hour_start
13
14
  case pointer
14
15
  when :future
15
16
  @current_hour_start = Chronic.construct(@now.year, @now.month, @now.day, @now.hour + 1)
@@ -55,4 +56,4 @@ module Chronic
55
56
  super << '-hour'
56
57
  end
57
58
  end
58
- end
59
+ end
@@ -2,14 +2,15 @@ module Chronic
2
2
  class RepeaterMinute < Repeater #:nodoc:
3
3
  MINUTE_SECONDS = 60
4
4
 
5
- def initialize(type)
5
+ def initialize(type, options = {})
6
6
  super
7
+ @current_minute_start = nil
7
8
  end
8
9
 
9
10
  def next(pointer = :future)
10
11
  super
11
12
 
12
- if !@current_minute_start
13
+ unless @current_minute_start
13
14
  case pointer
14
15
  when :future
15
16
  @current_minute_start = Chronic.construct(@now.year, @now.month, @now.day, @now.hour, @now.min + 1)
@@ -55,4 +56,4 @@ module Chronic
55
56
  super << '-minute'
56
57
  end
57
58
  end
58
- end
59
+ end
@@ -5,14 +5,15 @@ module Chronic
5
5
  MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
6
6
  MONTH_DAYS_LEAP = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
7
7
 
8
- def initialize(type)
8
+ def initialize(type, options = {})
9
9
  super
10
+ @current_month_start = nil
10
11
  end
11
12
 
12
13
  def next(pointer)
13
14
  super
14
15
 
15
- if !@current_month_start
16
+ unless @current_month_start
16
17
  @current_month_start = offset_by(Chronic.construct(@now.year, @now.month), 1, pointer)
17
18
  else
18
19
  @current_month_start = offset_by(Chronic.construct(@current_month_start.year, @current_month_start.month), 1, pointer)
@@ -73,7 +74,7 @@ module Chronic
73
74
  private
74
75
 
75
76
  def month_days(year, month)
76
- Date.leap?(year) ? MONTH_DAYS_LEAP[month - 1] : MONTH_DAYS[month - 1]
77
+ ::Date.leap?(year) ? MONTH_DAYS_LEAP[month - 1] : MONTH_DAYS[month - 1]
77
78
  end
78
79
  end
79
- end
80
+ end
@@ -16,14 +16,15 @@ module Chronic
16
16
  :december => 12
17
17
  }
18
18
 
19
- def initialize(type)
19
+ def initialize(type, options = {})
20
20
  super
21
+ @current_month_begin = nil
21
22
  end
22
23
 
23
24
  def next(pointer)
24
25
  super
25
26
 
26
- if !@current_month_begin
27
+ unless @current_month_begin
27
28
  case pointer
28
29
  when :future
29
30
  if @now.month < index
@@ -91,4 +92,4 @@ module Chronic
91
92
  super << '-monthname-' << @type.to_s
92
93
  end
93
94
  end
94
- end
95
+ end
@@ -8,8 +8,10 @@ module Chronic
8
8
  :winter => Season.new(MiniDate.new(12,22), MiniDate.new(3,19))
9
9
  }
10
10
 
11
- def initialize(type)
11
+ def initialize(type, options = {})
12
12
  super
13
+ @next_season_start = nil
14
+ @next_season_end = nil
13
15
  end
14
16
 
15
17
  def next(pointer)
@@ -63,7 +65,7 @@ module Chronic
63
65
  private
64
66
 
65
67
  def find_next_season_span(direction, next_season)
66
- unless @next_season_start or @next_season_end
68
+ unless @next_season_start || @next_season_end
67
69
  @next_season_start = Chronic.construct(@now.year, @now.month, @now.day)
68
70
  @next_season_end = Chronic.construct(@now.year, @now.month, @now.day)
69
71
  end
@@ -106,4 +108,4 @@ module Chronic
106
108
  )
107
109
  end
108
110
  end
109
- end
111
+ end
@@ -2,8 +2,9 @@ module Chronic
2
2
  class RepeaterSecond < Repeater #:nodoc:
3
3
  SECOND_SECONDS = 1 # haha, awesome
4
4
 
5
- def initialize(type)
5
+ def initialize(type, options = {})
6
6
  super
7
+ @second_start = nil
7
8
  end
8
9
 
9
10
  def next(pointer = :future)
@@ -11,7 +12,7 @@ module Chronic
11
12
 
12
13
  direction = pointer == :future ? 1 : -1
13
14
 
14
- if !@second_start
15
+ unless @second_start
15
16
  @second_start = @now + (direction * SECOND_SECONDS)
16
17
  else
17
18
  @second_start += SECOND_SECONDS * direction
@@ -39,4 +40,4 @@ module Chronic
39
40
  super << '-second'
40
41
  end
41
42
  end
42
- end
43
+ end
@@ -26,31 +26,41 @@ module Chronic
26
26
 
27
27
  end
28
28
 
29
- def initialize(time)
30
- t = time.gsub(/\:/, '')
31
-
32
- @type =
33
- case t.size
34
- when 1..2
35
- hours = t.to_i
36
- Tick.new((hours == 12 ? 0 : hours) * 60 * 60, true)
37
- when 3
38
- hours = t[0..0].to_i
39
- ambiguous = hours > 0
40
- Tick.new((hours * 60 * 60) + (t[1..2].to_i * 60), ambiguous)
41
- when 4
42
- ambiguous = time =~ /:/ && t[0..0].to_i != 0 && t[0..1].to_i <= 12
43
- hours = t[0..1].to_i
44
- hours == 12 ? Tick.new(0 * 60 * 60 + t[2..3].to_i * 60, ambiguous) : Tick.new(hours * 60 * 60 + t[2..3].to_i * 60, ambiguous)
45
- when 5
46
- Tick.new(t[0..0].to_i * 60 * 60 + t[1..2].to_i * 60 + t[3..4].to_i, true)
47
- when 6
48
- ambiguous = time =~ /:/ && t[0..0].to_i != 0 && t[0..1].to_i <= 12
49
- hours = t[0..1].to_i
50
- hours == 12 ? Tick.new(0 * 60 * 60 + t[2..3].to_i * 60 + t[4..5].to_i, ambiguous) : Tick.new(hours * 60 * 60 + t[2..3].to_i * 60 + t[4..5].to_i, ambiguous)
51
- else
52
- raise("Time cannot exceed six digits")
29
+ def initialize(time, options = {})
30
+ @current_time = nil
31
+ @options = options
32
+ time_parts = time.split(':')
33
+ raise ArgumentError, "Time cannot have more than 4 groups of ':'" if time_parts.count > 4
34
+
35
+ if time_parts.first.length > 2 and time_parts.count == 1
36
+ if time_parts.first.length > 4
37
+ second_index = time_parts.first.length - 2
38
+ time_parts.insert(1, time_parts.first[second_index..time_parts.first.length])
39
+ time_parts[0] = time_parts.first[0..second_index - 1]
40
+ end
41
+ minute_index = time_parts.first.length - 2
42
+ time_parts.insert(1, time_parts.first[minute_index..time_parts.first.length])
43
+ time_parts[0] = time_parts.first[0..minute_index - 1]
44
+ end
45
+
46
+ ambiguous = false
47
+ hours = time_parts.first.to_i
48
+
49
+ if @options[:hours24].nil? or (not @options[:hours24].nil? and @options[:hours24] != true)
50
+ ambiguous = true if (time_parts.first.length == 1 and hours > 0) or (hours >= 10 and hours <= 12) or (@options[:hours24] == false and hours > 0)
51
+ hours = 0 if hours == 12 and ambiguous
53
52
  end
53
+
54
+ hours *= 60 * 60
55
+ minutes = 0
56
+ seconds = 0
57
+ subseconds = 0
58
+
59
+ minutes = time_parts[1].to_i * 60 if time_parts.count > 1
60
+ seconds = time_parts[2].to_i if time_parts.count > 2
61
+ subseconds = time_parts[3].to_f / (10 ** time_parts[3].length) if time_parts.count > 3
62
+
63
+ @type = Tick.new(hours + minutes + seconds + subseconds, ambiguous)
54
64
  end
55
65
 
56
66
  # Return the next past or future Span for the time that this Repeater represents
@@ -125,4 +135,4 @@ module Chronic
125
135
  super << '-time-' << @type.to_s
126
136
  end
127
137
  end
128
- end
138
+ end
@@ -2,14 +2,15 @@ module Chronic
2
2
  class RepeaterWeek < Repeater #:nodoc:
3
3
  WEEK_SECONDS = 604800 # (7 * 24 * 60 * 60)
4
4
 
5
- def initialize(type)
5
+ def initialize(type, options = {})
6
6
  super
7
+ @current_week_start = nil
7
8
  end
8
9
 
9
10
  def next(pointer)
10
11
  super
11
12
 
12
- if !@current_week_start
13
+ unless @current_week_start
13
14
  case pointer
14
15
  when :future
15
16
  sunday_repeater = RepeaterDayName.new(:sunday)
@@ -71,4 +72,4 @@ module Chronic
71
72
  super << '-week'
72
73
  end
73
74
  end
74
- end
75
+ end
@@ -11,8 +11,9 @@ module Chronic
11
11
  :saturday => 6
12
12
  }
13
13
 
14
- def initialize(type)
14
+ def initialize(type, options = {})
15
15
  super
16
+ @current_weekday_start = nil
16
17
  end
17
18
 
18
19
  def next(pointer)
@@ -20,7 +21,7 @@ module Chronic
20
21
 
21
22
  direction = pointer == :future ? 1 : -1
22
23
 
23
- if !@current_weekday_start
24
+ unless @current_weekday_start
24
25
  @current_weekday_start = Chronic.construct(@now.year, @now.month, @now.day)
25
26
  @current_weekday_start += direction * DAY_SECONDS
26
27
 
@@ -82,4 +83,4 @@ module Chronic
82
83
  DAYS[sym] || raise("Invalid symbol specified")
83
84
  end
84
85
  end
85
- end
86
+ end
@@ -2,14 +2,15 @@ module Chronic
2
2
  class RepeaterWeekend < Repeater #:nodoc:
3
3
  WEEKEND_SECONDS = 172_800 # (2 * 24 * 60 * 60)
4
4
 
5
- def initialize(type)
5
+ def initialize(type, options = {})
6
6
  super
7
+ @current_week_start = nil
7
8
  end
8
9
 
9
10
  def next(pointer)
10
11
  super
11
12
 
12
- if !@current_week_start
13
+ unless @current_week_start
13
14
  case pointer
14
15
  when :future
15
16
  saturday_repeater = RepeaterDayName.new(:saturday)
@@ -63,4 +64,4 @@ module Chronic
63
64
  super << '-weekend'
64
65
  end
65
66
  end
66
- end
67
+ end