chronic 0.2.2 → 0.10.2

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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.travis.yml +8 -0
  4. data/HISTORY.md +243 -0
  5. data/LICENSE +21 -0
  6. data/README.md +182 -0
  7. data/Rakefile +62 -15
  8. data/chronic.gemspec +23 -0
  9. data/lib/chronic/date.rb +82 -0
  10. data/lib/chronic/grabber.rb +24 -17
  11. data/lib/chronic/handler.rb +97 -0
  12. data/lib/chronic/handlers.rb +490 -312
  13. data/lib/chronic/mini_date.rb +38 -0
  14. data/lib/chronic/numerizer.rb +130 -0
  15. data/lib/chronic/ordinal.rb +33 -24
  16. data/lib/chronic/parser.rb +268 -0
  17. data/lib/chronic/pointer.rb +22 -17
  18. data/lib/chronic/repeater.rb +137 -107
  19. data/lib/chronic/repeaters/repeater_day.rb +51 -44
  20. data/lib/chronic/repeaters/repeater_day_name.rb +50 -43
  21. data/lib/chronic/repeaters/repeater_day_portion.rb +97 -81
  22. data/lib/chronic/repeaters/repeater_fortnight.rb +61 -54
  23. data/lib/chronic/repeaters/repeater_hour.rb +51 -44
  24. data/lib/chronic/repeaters/repeater_minute.rb +51 -44
  25. data/lib/chronic/repeaters/repeater_month.rb +79 -60
  26. data/lib/chronic/repeaters/repeater_month_name.rb +85 -83
  27. data/lib/chronic/repeaters/repeater_season.rb +110 -22
  28. data/lib/chronic/repeaters/repeater_season_name.rb +41 -22
  29. data/lib/chronic/repeaters/repeater_second.rb +41 -34
  30. data/lib/chronic/repeaters/repeater_time.rb +128 -104
  31. data/lib/chronic/repeaters/repeater_week.rb +65 -58
  32. data/lib/chronic/repeaters/repeater_weekday.rb +86 -0
  33. data/lib/chronic/repeaters/repeater_weekend.rb +59 -52
  34. data/lib/chronic/repeaters/repeater_year.rb +72 -52
  35. data/lib/chronic/scalar.rb +53 -46
  36. data/lib/chronic/season.rb +26 -0
  37. data/lib/chronic/separator.rb +174 -43
  38. data/lib/chronic/sign.rb +49 -0
  39. data/lib/chronic/span.rb +31 -0
  40. data/lib/chronic/tag.rb +37 -0
  41. data/lib/chronic/time.rb +40 -0
  42. data/lib/chronic/time_zone.rb +21 -11
  43. data/lib/chronic/token.rb +51 -0
  44. data/lib/chronic.rb +94 -69
  45. data/test/helper.rb +12 -0
  46. data/test/test_chronic.rb +183 -0
  47. data/test/test_daylight_savings.rb +118 -0
  48. data/test/{test_Handler.rb → test_handler.rb} +73 -55
  49. data/test/test_mini_date.rb +32 -0
  50. data/test/test_numerizer.rb +86 -0
  51. data/test/test_parsing.rb +891 -248
  52. data/test/{test_RepeaterDayName.rb → test_repeater_day_name.rb} +16 -17
  53. data/test/test_repeater_day_portion.rb +254 -0
  54. data/test/{test_RepeaterFortnight.rb → test_repeater_fortnight.rb} +17 -18
  55. data/test/{test_RepeaterHour.rb → test_repeater_hour.rb} +23 -20
  56. data/test/test_repeater_minute.rb +34 -0
  57. data/test/{test_RepeaterMonth.rb → test_repeater_month.rb} +21 -18
  58. data/test/{test_RepeaterMonthName.rb → test_repeater_month_name.rb} +18 -19
  59. data/test/test_repeater_season.rb +40 -0
  60. data/test/{test_RepeaterTime.rb → test_repeater_time.rb} +39 -23
  61. data/test/{test_RepeaterWeek.rb → test_repeater_week.rb} +17 -18
  62. data/test/test_repeater_weekday.rb +55 -0
  63. data/test/{test_RepeaterWeekend.rb → test_repeater_weekend.rb} +22 -23
  64. data/test/{test_RepeaterYear.rb → test_repeater_year.rb} +25 -19
  65. data/test/{test_Span.rb → test_span.rb} +7 -8
  66. data/test/{test_Token.rb → test_token.rb} +6 -7
  67. metadata +163 -85
  68. data/History.txt +0 -49
  69. data/Manifest.txt +0 -47
  70. data/README.txt +0 -149
  71. data/lib/chronic/chronic.rb +0 -239
  72. data/lib/numerizer/numerizer.rb +0 -103
  73. data/test/suite.rb +0 -9
  74. data/test/test_Chronic.rb +0 -50
  75. data/test/test_Numerizer.rb +0 -48
  76. data/test/test_Time.rb +0 -50
data/lib/chronic.rb CHANGED
@@ -1,16 +1,25 @@
1
- #=============================================================================
2
- #
3
- # Name: Chronic
4
- # Author: Tom Preston-Werner
5
- # Purpose: Parse natural language dates and times into Time or
6
- # Chronic::Span objects
7
- #
8
- #=============================================================================
1
+ require 'time'
2
+ require 'date'
9
3
 
10
- $:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
4
+ require 'chronic/parser'
5
+ require 'chronic/date'
6
+ require 'chronic/time'
11
7
 
12
- require 'chronic/chronic'
8
+ require 'chronic/handler'
13
9
  require 'chronic/handlers'
10
+ require 'chronic/mini_date'
11
+ require 'chronic/tag'
12
+ require 'chronic/span'
13
+ require 'chronic/token'
14
+ require 'chronic/grabber'
15
+ require 'chronic/pointer'
16
+ require 'chronic/scalar'
17
+ require 'chronic/ordinal'
18
+ require 'chronic/separator'
19
+ require 'chronic/sign'
20
+ require 'chronic/time_zone'
21
+ require 'chronic/numerizer'
22
+ require 'chronic/season'
14
23
 
15
24
  require 'chronic/repeater'
16
25
  require 'chronic/repeaters/repeater_year'
@@ -21,6 +30,7 @@ require 'chronic/repeaters/repeater_month_name'
21
30
  require 'chronic/repeaters/repeater_fortnight'
22
31
  require 'chronic/repeaters/repeater_week'
23
32
  require 'chronic/repeaters/repeater_weekend'
33
+ require 'chronic/repeaters/repeater_weekday'
24
34
  require 'chronic/repeaters/repeater_day'
25
35
  require 'chronic/repeaters/repeater_day_name'
26
36
  require 'chronic/repeaters/repeater_day_portion'
@@ -29,87 +39,95 @@ require 'chronic/repeaters/repeater_minute'
29
39
  require 'chronic/repeaters/repeater_second'
30
40
  require 'chronic/repeaters/repeater_time'
31
41
 
32
- require 'chronic/grabber'
33
- require 'chronic/pointer'
34
- require 'chronic/scalar'
35
- require 'chronic/ordinal'
36
- require 'chronic/separator'
37
- require 'chronic/time_zone'
42
+ # Parse natural language dates and times into Time or Chronic::Span objects.
43
+ #
44
+ # Examples:
45
+ #
46
+ # require 'chronic'
47
+ #
48
+ # Time.now #=> Sun Aug 27 23:18:25 PDT 2006
49
+ #
50
+ # Chronic.parse('tomorrow')
51
+ # #=> Mon Aug 28 12:00:00 PDT 2006
52
+ #
53
+ # Chronic.parse('monday', :context => :past)
54
+ # #=> Mon Aug 21 12:00:00 PDT 2006
55
+ module Chronic
56
+ VERSION = "0.10.2"
38
57
 
39
- require 'numerizer/numerizer'
58
+ class << self
40
59
 
41
- module Chronic
42
- VERSION = "0.2.2"
43
-
44
- def self.debug; false; end
45
- end
60
+ # Returns true when debug mode is enabled.
61
+ attr_accessor :debug
46
62
 
47
- alias p_orig p
63
+ # Examples:
64
+ #
65
+ # require 'chronic'
66
+ # require 'active_support/time'
67
+ #
68
+ # Time.zone = 'UTC'
69
+ # Chronic.time_class = Time.zone
70
+ # Chronic.parse('June 15 2006 at 5:54 AM')
71
+ # # => Thu, 15 Jun 2006 05:45:00 UTC +00:00
72
+ #
73
+ # Returns The Time class Chronic uses internally.
74
+ attr_accessor :time_class
75
+ end
48
76
 
49
- def p(val)
50
- p_orig val
51
- puts
52
- end
77
+ self.debug = false
78
+ self.time_class = ::Time
53
79
 
54
- # class Time
55
- # def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0)
56
- # # extra_seconds = second > 60 ? second - 60 : 0
57
- # # extra_minutes = minute > 59 ? minute - 59 : 0
58
- # # extra_hours = hour > 23 ? hour - 23 : 0
59
- # # extra_days = day >
60
- #
61
- # if month > 12
62
- # if month % 12 == 0
63
- # year += (month - 12) / 12
64
- # month = 12
65
- # else
66
- # year += month / 12
67
- # month = month % 12
68
- # end
69
- # end
70
- #
71
- # base = Time.local(year, month)
72
- # puts base
73
- # offset = ((day - 1) * 24 * 60 * 60) + (hour * 60 * 60) + (minute * 60) + second
74
- # puts offset.to_s
75
- # date = base + offset
76
- # puts date
77
- # date
78
- # end
79
- # end
80
-
81
- class Time
82
- def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0)
80
+
81
+ # Parses a string containing a natural language date or time.
82
+ #
83
+ # If the parser can find a date or time, either a Time or Chronic::Span
84
+ # will be returned (depending on the value of `:guess`). If no
85
+ # date or time can be found, `nil` will be returned.
86
+ #
87
+ # text - The String text to parse.
88
+ # opts - An optional Hash of configuration options passed to Parser::new.
89
+ def self.parse(text, options = {})
90
+ Parser.new(options).parse(text)
91
+ end
92
+
93
+ # Construct a new time object determining possible month overflows
94
+ # and leap years.
95
+ #
96
+ # year - Integer year.
97
+ # month - Integer month.
98
+ # day - Integer day.
99
+ # hour - Integer hour.
100
+ # minute - Integer minute.
101
+ # second - Integer second.
102
+ #
103
+ # Returns a new Time object constructed from these params.
104
+ def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0, offset = nil)
83
105
  if second >= 60
84
106
  minute += second / 60
85
107
  second = second % 60
86
108
  end
87
-
109
+
88
110
  if minute >= 60
89
111
  hour += minute / 60
90
112
  minute = minute % 60
91
113
  end
92
-
114
+
93
115
  if hour >= 24
94
116
  day += hour / 24
95
117
  hour = hour % 24
96
118
  end
97
-
119
+
98
120
  # determine if there is a day overflow. this is complicated by our crappy calendar
99
121
  # system (non-constant number of days per month)
100
122
  day <= 56 || raise("day must be no more than 56 (makes month resolution easier)")
101
- if day > 28
102
- # no month ever has fewer than 28 days, so only do this if necessary
103
- leap_year = (year % 4 == 0) && !(year % 100 == 0)
104
- leap_year_month_days = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
105
- common_year_month_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
106
- days_this_month = leap_year ? leap_year_month_days[month - 1] : common_year_month_days[month - 1]
123
+ if day > 28 # no month ever has fewer than 28 days, so only do this if necessary
124
+ days_this_month = ::Date.leap?(year) ? Date::MONTH_DAYS_LEAP[month] : Date::MONTH_DAYS[month]
107
125
  if day > days_this_month
108
126
  month += day / days_this_month
109
127
  day = day % days_this_month
110
128
  end
111
129
  end
112
-
130
+
113
131
  if month > 12
114
132
  if month % 12 == 0
115
133
  year += (month - 12) / 12
@@ -119,7 +137,14 @@ class Time
119
137
  month = month % 12
120
138
  end
121
139
  end
122
-
123
- Time.local(year, month, day, hour, minute, second)
140
+ if Chronic.time_class.name == "Date"
141
+ Chronic.time_class.new(year, month, day)
142
+ elsif not Chronic.time_class.respond_to?(:new) or (RUBY_VERSION.to_f < 1.9 and Chronic.time_class.name == "Time")
143
+ Chronic.time_class.local(year, month, day, hour, minute, second)
144
+ else
145
+ offset = Time::normalize_offset(offset) if Chronic.time_class.name == "DateTime"
146
+ Chronic.time_class.new(year, month, day, hour, minute, second, offset)
147
+ end
124
148
  end
125
- end
149
+
150
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,12 @@
1
+ unless defined? Chronic
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'chronic'
4
+ end
5
+
6
+ require 'minitest/autorun'
7
+
8
+ class TestCase < MiniTest::Test
9
+ def self.test(name, &block)
10
+ define_method("test_#{name.gsub(/\W/, '_')}", &block) if block
11
+ end
12
+ end
@@ -0,0 +1,183 @@
1
+ require 'helper'
2
+
3
+ class TestChronic < TestCase
4
+
5
+ def setup
6
+ # Wed Aug 16 14:00:00 UTC 2006
7
+ @now = Time.local(2006, 8, 16, 14, 0, 0, 0)
8
+ end
9
+
10
+ def test_pre_normalize
11
+ assert_equal Chronic::Parser.new.pre_normalize('12:55 pm'), Chronic::Parser.new.pre_normalize('12.55 pm')
12
+ end
13
+
14
+ def test_pre_normalize_numerized_string
15
+ string = 'two and a half years'
16
+ assert_equal Chronic::Numerizer.numerize(string), Chronic::Parser.new.pre_normalize(string)
17
+ end
18
+
19
+ def test_post_normalize_am_pm_aliases
20
+ # affect wanted patterns
21
+
22
+ tokens = [Chronic::Token.new("5:00"), Chronic::Token.new("morning")]
23
+ tokens[0].tag(Chronic::RepeaterTime.new("5:00"))
24
+ tokens[1].tag(Chronic::RepeaterDayPortion.new(:morning))
25
+
26
+ assert_equal :morning, tokens[1].tags[0].type
27
+
28
+ tokens = Chronic::Handlers.dealias_and_disambiguate_times(tokens, {})
29
+
30
+ assert_equal :am, tokens[1].tags[0].type
31
+ assert_equal 2, tokens.size
32
+
33
+ # don't affect unwanted patterns
34
+
35
+ tokens = [Chronic::Token.new("friday"), Chronic::Token.new("morning")]
36
+ tokens[0].tag(Chronic::RepeaterDayName.new(:friday))
37
+ tokens[1].tag(Chronic::RepeaterDayPortion.new(:morning))
38
+
39
+ assert_equal :morning, tokens[1].tags[0].type
40
+
41
+ tokens = Chronic::Handlers.dealias_and_disambiguate_times(tokens, {})
42
+
43
+ assert_equal :morning, tokens[1].tags[0].type
44
+ assert_equal 2, tokens.size
45
+ end
46
+
47
+ def test_guess
48
+ span = Chronic::Span.new(Time.local(2006, 8, 16, 0), Time.local(2006, 8, 17, 0))
49
+ assert_equal Time.local(2006, 8, 16, 12), Chronic::Parser.new.guess(span)
50
+
51
+ span = Chronic::Span.new(Time.local(2006, 8, 16, 0), Time.local(2006, 8, 17, 0, 0, 1))
52
+ assert_equal Time.local(2006, 8, 16, 12), Chronic::Parser.new.guess(span)
53
+
54
+ span = Chronic::Span.new(Time.local(2006, 11), Time.local(2006, 12))
55
+ assert_equal Time.local(2006, 11, 16), Chronic::Parser.new.guess(span)
56
+ end
57
+
58
+ def test_endian_definitions
59
+ # middle, little
60
+ endians = [
61
+ Chronic::Handler.new([:scalar_month, [:separator_slash, :separator_dash], :scalar_day, [:separator_slash, :separator_dash], :scalar_year, :separator_at?, 'time?'], :handle_sm_sd_sy),
62
+ Chronic::Handler.new([:scalar_month, [:separator_slash, :separator_dash], :scalar_day, :separator_at?, 'time?'], :handle_sm_sd),
63
+ Chronic::Handler.new([:scalar_day, [:separator_slash, :separator_dash], :scalar_month, :separator_at?, 'time?'], :handle_sd_sm),
64
+ Chronic::Handler.new([:scalar_day, [:separator_slash, :separator_dash], :scalar_month, [:separator_slash, :separator_dash], :scalar_year, :separator_at?, 'time?'], :handle_sd_sm_sy)
65
+ ]
66
+
67
+ assert_equal endians, Chronic::Parser.new.definitions[:endian]
68
+
69
+ defs = Chronic::Parser.new.definitions(:endian_precedence => :little)
70
+ assert_equal endians.reverse, defs[:endian]
71
+
72
+ defs = Chronic::Parser.new.definitions(:endian_precedence => [:little, :middle])
73
+ assert_equal endians.reverse, defs[:endian]
74
+
75
+ assert_raises(ArgumentError) do
76
+ Chronic::Parser.new.definitions(:endian_precedence => :invalid)
77
+ end
78
+ end
79
+
80
+ def test_debug
81
+ require 'stringio'
82
+ $stdout = StringIO.new
83
+ Chronic.debug = true
84
+
85
+ Chronic.parse 'now'
86
+ assert $stdout.string.include?('this(grabber-this)')
87
+ ensure
88
+ $stdout = STDOUT
89
+ Chronic.debug = false
90
+ end
91
+
92
+ # Chronic.construct
93
+
94
+ def test_normal
95
+ assert_equal Time.local(2006, 1, 2, 0, 0, 0), Chronic.construct(2006, 1, 2, 0, 0, 0)
96
+ assert_equal Time.local(2006, 1, 2, 3, 0, 0), Chronic.construct(2006, 1, 2, 3, 0, 0)
97
+ assert_equal Time.local(2006, 1, 2, 3, 4, 0), Chronic.construct(2006, 1, 2, 3, 4, 0)
98
+ assert_equal Time.local(2006, 1, 2, 3, 4, 5), Chronic.construct(2006, 1, 2, 3, 4, 5)
99
+ end
100
+
101
+ def test_second_overflow
102
+ assert_equal Time.local(2006, 1, 1, 0, 1, 30), Chronic.construct(2006, 1, 1, 0, 0, 90)
103
+ assert_equal Time.local(2006, 1, 1, 0, 5, 0), Chronic.construct(2006, 1, 1, 0, 0, 300)
104
+ end
105
+
106
+ def test_minute_overflow
107
+ assert_equal Time.local(2006, 1, 1, 1, 30), Chronic.construct(2006, 1, 1, 0, 90)
108
+ assert_equal Time.local(2006, 1, 1, 5), Chronic.construct(2006, 1, 1, 0, 300)
109
+ end
110
+
111
+ def test_hour_overflow
112
+ assert_equal Time.local(2006, 1, 2, 12), Chronic.construct(2006, 1, 1, 36)
113
+ assert_equal Time.local(2006, 1, 7), Chronic.construct(2006, 1, 1, 144)
114
+ end
115
+
116
+ def test_day_overflow
117
+ assert_equal Time.local(2006, 2, 1), Chronic.construct(2006, 1, 32)
118
+ assert_equal Time.local(2006, 3, 5), Chronic.construct(2006, 2, 33)
119
+ assert_equal Time.local(2004, 3, 4), Chronic.construct(2004, 2, 33)
120
+ assert_equal Time.local(2000, 3, 4), Chronic.construct(2000, 2, 33)
121
+
122
+ assert_raises(RuntimeError) do
123
+ Chronic.construct(2006, 1, 57)
124
+ end
125
+ end
126
+
127
+ def test_month_overflow
128
+ assert_equal Time.local(2006, 1), Chronic.construct(2005, 13)
129
+ assert_equal Time.local(2005, 12), Chronic.construct(2000, 72)
130
+ end
131
+
132
+ def test_time
133
+ org = Chronic.time_class
134
+ begin
135
+ Chronic.time_class = ::Time
136
+ assert_equal ::Time.new(2013, 8, 27, 20, 30, 40, '+05:30'), Chronic.construct(2013, 8, 27, 20, 30, 40, '+05:30')
137
+ assert_equal ::Time.new(2013, 8, 27, 20, 30, 40, '-08:00'), Chronic.construct(2013, 8, 27, 20, 30, 40, -28800)
138
+ ensure
139
+ Chronic.time_class = org
140
+ end
141
+ end
142
+
143
+ def test_date
144
+ org = Chronic.time_class
145
+ begin
146
+ Chronic.time_class = ::Date
147
+ assert_equal Date.new(2013, 8, 27), Chronic.construct(2013, 8, 27)
148
+ ensure
149
+ Chronic.time_class = org
150
+ end
151
+ end
152
+
153
+ def test_datetime
154
+ org = Chronic.time_class
155
+ begin
156
+ Chronic.time_class = ::DateTime
157
+ assert_equal DateTime.new(2013, 8, 27, 20, 30, 40, '+05:30'), Chronic.construct(2013, 8, 27, 20, 30, 40, '+05:30')
158
+ assert_equal DateTime.new(2013, 8, 27, 20, 30, 40, '-08:00'), Chronic.construct(2013, 8, 27, 20, 30, 40, -28800)
159
+ ensure
160
+ Chronic.time_class = org
161
+ end
162
+ end
163
+
164
+ def test_activesupport
165
+ =begin
166
+ # ActiveSupport needs MiniTest '~> 4.2' which conflicts with '~> 5.0'
167
+ require 'active_support/time'
168
+ org = Chronic.time_class
169
+ org_zone = ::Time.zone
170
+ begin
171
+ ::Time.zone = "Tokyo"
172
+ Chronic.time_class = ::Time.zone
173
+ assert_equal Time.new(2013, 8, 27, 20, 30, 40, '+09:00'), Chronic.construct(2013, 8, 27, 20, 30, 40)
174
+ ::Time.zone = "Indiana (East)"
175
+ Chronic.time_class = ::Time.zone
176
+ assert_equal Time.new(2013, 8, 27, 20, 30, 40, -14400), Chronic.construct(2013, 8, 27, 20, 30, 40)
177
+ ensure
178
+ Chronic.time_class = org
179
+ ::Time.zone = org_zone
180
+ end
181
+ =end
182
+ end
183
+ end
@@ -0,0 +1,118 @@
1
+ require 'helper'
2
+
3
+ class TestDaylightSavings < TestCase
4
+
5
+ def setup
6
+ @begin_daylight_savings = Time.local(2008, 3, 9, 5, 0, 0, 0)
7
+ @end_daylight_savings = Time.local(2008, 11, 2, 5, 0, 0, 0)
8
+ end
9
+
10
+ def test_begin_past
11
+ # ambiguous - resolve to last night
12
+ t = Chronic::RepeaterTime.new('900')
13
+ t.start = @begin_daylight_savings
14
+ assert_equal Time.local(2008, 3, 8, 21), t.next(:past).begin
15
+
16
+ # ambiguous - resolve to this afternoon
17
+ t = Chronic::RepeaterTime.new('900')
18
+ t.start = Time.local(2008, 3, 9, 22, 0, 0, 0)
19
+ assert_equal Time.local(2008, 3, 9, 21), t.next(:past).begin
20
+
21
+ # ambiguous - resolve to this morning
22
+ t = Chronic::RepeaterTime.new('400')
23
+ t.start = @begin_daylight_savings
24
+ assert_equal Time.local(2008, 3, 9, 4), t.next(:past).begin
25
+
26
+ # unambiguous - resolve to today
27
+ t = Chronic::RepeaterTime.new('0400')
28
+ t.start = @begin_daylight_savings
29
+ assert_equal Time.local(2008, 3, 9, 4), t.next(:past).begin
30
+
31
+ # unambiguous - resolve to yesterday
32
+ t = Chronic::RepeaterTime.new('1300')
33
+ t.start = @begin_daylight_savings
34
+ assert_equal Time.local(2008, 3, 8, 13), t.next(:past).begin
35
+ end
36
+
37
+ def test_begin_future
38
+ # ambiguous - resolve to this morning
39
+ t = Chronic::RepeaterTime.new('900')
40
+ t.start = @begin_daylight_savings
41
+ assert_equal Time.local(2008, 3, 9, 9), t.next(:future).begin
42
+
43
+ # ambiguous - resolve to this afternoon
44
+ t = Chronic::RepeaterTime.new('900')
45
+ t.start = Time.local(2008, 3, 9, 13, 0, 0, 0)
46
+ assert_equal Time.local(2008, 3, 9, 21), t.next(:future).begin
47
+
48
+ # ambiguous - resolve to tomorrow
49
+ t = Chronic::RepeaterTime.new('900')
50
+ t.start = Time.local(2008, 3, 9, 22, 0, 0, 0)
51
+ assert_equal Time.local(2008, 3, 10, 9), t.next(:future).begin
52
+
53
+ # unambiguous - resolve to today
54
+ t = Chronic::RepeaterTime.new('0900')
55
+ t.start = @begin_daylight_savings
56
+ assert_equal Time.local(2008, 3, 9, 9), t.next(:future).begin
57
+
58
+ # unambiguous - resolve to tomorrow
59
+ t = Chronic::RepeaterTime.new('0400')
60
+ t.start = @begin_daylight_savings
61
+ assert_equal Time.local(2008, 3, 10, 4), t.next(:future).begin
62
+ end
63
+
64
+ def test_end_past
65
+ # ambiguous - resolve to last night
66
+ t = Chronic::RepeaterTime.new('900')
67
+ t.start = @end_daylight_savings
68
+ assert_equal Time.local(2008, 11, 1, 21), t.next(:past).begin
69
+
70
+ # ambiguous - resolve to this afternoon
71
+ t = Chronic::RepeaterTime.new('900')
72
+ t.start = Time.local(2008, 11, 2, 22, 0, 0, 0)
73
+ assert_equal Time.local(2008, 11, 2, 21), t.next(:past).begin
74
+
75
+ # ambiguous - resolve to this morning
76
+ t = Chronic::RepeaterTime.new('400')
77
+ t.start = @end_daylight_savings
78
+ assert_equal Time.local(2008, 11, 2, 4), t.next(:past).begin
79
+
80
+ # unambiguous - resolve to today
81
+ t = Chronic::RepeaterTime.new('0400')
82
+ t.start = @end_daylight_savings
83
+ assert_equal Time.local(2008, 11, 2, 4), t.next(:past).begin
84
+
85
+ # unambiguous - resolve to yesterday
86
+ t = Chronic::RepeaterTime.new('1300')
87
+ t.start = @end_daylight_savings
88
+ assert_equal Time.local(2008, 11, 1, 13), t.next(:past).begin
89
+ end
90
+
91
+ def test_end_future
92
+ # ambiguous - resolve to this morning
93
+ t = Chronic::RepeaterTime.new('900')
94
+ t.start = @end_daylight_savings
95
+ assert_equal Time.local(2008, 11, 2, 9), t.next(:future).begin
96
+
97
+ # ambiguous - resolve to this afternoon
98
+ t = Chronic::RepeaterTime.new('900')
99
+ t.start = Time.local(2008, 11, 2, 13, 0, 0, 0)
100
+ assert_equal Time.local(2008, 11, 2, 21), t.next(:future).begin
101
+
102
+ # ambiguous - resolve to tomorrow
103
+ t = Chronic::RepeaterTime.new('900')
104
+ t.start = Time.local(2008, 11, 2, 22, 0, 0, 0)
105
+ assert_equal Time.local(2008, 11, 3, 9), t.next(:future).begin
106
+
107
+ # unambiguous - resolve to today
108
+ t = Chronic::RepeaterTime.new('0900')
109
+ t.start = @end_daylight_savings
110
+ assert_equal Time.local(2008, 11, 2, 9), t.next(:future).begin
111
+
112
+ # unambiguous - resolve to tomorrow
113
+ t = Chronic::RepeaterTime.new('0400')
114
+ t.start = @end_daylight_savings
115
+ assert_equal Time.local(2008, 11, 3, 4), t.next(:future).begin
116
+ end
117
+
118
+ end