chronic 0.9.1 → 0.10.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.
- checksums.yaml +4 -4
- data/.gitignore +4 -4
- data/HISTORY.md +12 -0
- data/README.md +8 -0
- data/Rakefile +28 -8
- data/chronic.gemspec +7 -5
- data/lib/chronic.rb +10 -10
- data/lib/chronic/date.rb +82 -0
- data/lib/chronic/handler.rb +34 -25
- data/lib/chronic/handlers.rb +22 -3
- data/lib/chronic/ordinal.rb +22 -20
- data/lib/chronic/parser.rb +31 -26
- data/lib/chronic/repeater.rb +18 -18
- data/lib/chronic/repeaters/repeater_day.rb +4 -3
- data/lib/chronic/repeaters/repeater_day_name.rb +5 -4
- data/lib/chronic/repeaters/repeater_day_portion.rb +4 -3
- data/lib/chronic/repeaters/repeater_fortnight.rb +4 -3
- data/lib/chronic/repeaters/repeater_hour.rb +4 -3
- data/lib/chronic/repeaters/repeater_minute.rb +4 -3
- data/lib/chronic/repeaters/repeater_month.rb +5 -4
- data/lib/chronic/repeaters/repeater_month_name.rb +4 -3
- data/lib/chronic/repeaters/repeater_season.rb +5 -3
- data/lib/chronic/repeaters/repeater_second.rb +4 -3
- data/lib/chronic/repeaters/repeater_time.rb +35 -25
- data/lib/chronic/repeaters/repeater_week.rb +4 -3
- data/lib/chronic/repeaters/repeater_weekday.rb +4 -3
- data/lib/chronic/repeaters/repeater_weekend.rb +4 -3
- data/lib/chronic/repeaters/repeater_year.rb +5 -4
- data/lib/chronic/scalar.rb +34 -69
- data/lib/chronic/separator.rb +107 -8
- data/lib/chronic/sign.rb +49 -0
- data/lib/chronic/tag.rb +5 -4
- data/lib/chronic/time.rb +40 -0
- data/test/helper.rb +2 -2
- data/test/test_chronic.rb +4 -4
- data/test/test_handler.rb +20 -0
- data/test/test_parsing.rb +72 -3
- data/test/test_repeater_time.rb +18 -0
- metadata +24 -6
data/lib/chronic/parser.rb
CHANGED
@@ -8,6 +8,7 @@ module Chronic
|
|
8
8
|
DEFAULT_OPTIONS = {
|
9
9
|
:context => :future,
|
10
10
|
:now => nil,
|
11
|
+
:hours24 => nil,
|
11
12
|
:guess => true,
|
12
13
|
:ambiguous_time_range => 6,
|
13
14
|
:endian_precedence => [:middle, :little],
|
@@ -23,10 +24,13 @@ module Chronic
|
|
23
24
|
# given, it will assume it is in the past.
|
24
25
|
# :now - Time, all computations will be based off of time
|
25
26
|
# instead of Time.now.
|
27
|
+
# :hours24 - Time will be parsed as it would be 24 hour clock.
|
26
28
|
# :guess - By default the parser will guess a single point in time
|
27
29
|
# for the given date or time. If you'd rather have the
|
28
30
|
# entire time span returned, set this to false
|
29
|
-
# and a Chronic::Span will be returned.
|
31
|
+
# and a Chronic::Span will be returned. Setting :guess to :end
|
32
|
+
# will return last time from Span, to :middle for middle (same as just true)
|
33
|
+
# and :begin for first time from span.
|
30
34
|
# :ambiguous_time_range - If an Integer is given, ambiguous times
|
31
35
|
# (like 5:00) will be assumed to be within the range of
|
32
36
|
# that time in the AM to that time in the PM. For
|
@@ -58,9 +62,7 @@ module Chronic
|
|
58
62
|
|
59
63
|
puts "+#{'-' * 51}\n| #{tokens}\n+#{'-' * 51}" if Chronic.debug
|
60
64
|
|
61
|
-
if span
|
62
|
-
options[:guess] ? guess(span) : span
|
63
|
-
end
|
65
|
+
guess(span, options[:guess]) if span
|
64
66
|
end
|
65
67
|
|
66
68
|
# Clean up the specified text ready for parsing.
|
@@ -86,14 +88,16 @@ module Chronic
|
|
86
88
|
# Returns a new String ready for Chronic to parse.
|
87
89
|
def pre_normalize(text)
|
88
90
|
text = text.to_s.downcase
|
91
|
+
text.gsub!(/\b(\d{2})\.(\d{2})\.(\d{4})\b/, '\3 / \2 / \1')
|
89
92
|
text.gsub!(/\b([ap])\.m\.?/, '\1m')
|
93
|
+
text.gsub!(/(?<=:\d{2}|:\d{2}\.\d{3})\-(\d{2}:?\d{2})\b/, 'tzminus\1')
|
90
94
|
text.gsub!(/\./, ':')
|
95
|
+
text.gsub!(/([ap]):m:?/, '\1m')
|
91
96
|
text.gsub!(/['"]/, '')
|
92
97
|
text.gsub!(/,/, ' ')
|
93
98
|
text.gsub!(/^second /, '2nd ')
|
94
99
|
text.gsub!(/\bsecond (of|day|month|hour|minute|second)\b/, '2nd \1')
|
95
100
|
text = Numerizer.numerize(text)
|
96
|
-
text.gsub!(/\-(\d{2}:?\d{2})\b/, 'tzminus\1')
|
97
101
|
text.gsub!(/([\/\-\,\@])/) { ' ' + $1 + ' ' }
|
98
102
|
text.gsub!(/(?:^|\s)0(\d+:\d+\s*pm?\b)/, ' \1')
|
99
103
|
text.gsub!(/\btoday\b/, 'this day')
|
@@ -126,12 +130,11 @@ module Chronic
|
|
126
130
|
# span - The Chronic::Span object to calcuate a guess from.
|
127
131
|
#
|
128
132
|
# Returns a new Time object.
|
129
|
-
def guess(span)
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
133
|
+
def guess(span, mode = :middle)
|
134
|
+
return span if not mode
|
135
|
+
return span.begin + span.width / 2 if span.width > 1 and (mode == true or mode == :middle)
|
136
|
+
return span.end if mode == :end
|
137
|
+
span.begin
|
135
138
|
end
|
136
139
|
|
137
140
|
# List of Handler definitions. See Chronic.parse for a list of options this
|
@@ -149,19 +152,21 @@ module Chronic
|
|
149
152
|
],
|
150
153
|
|
151
154
|
:date => [
|
152
|
-
Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :repeater_time, :
|
155
|
+
Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :repeater_time, [:separator_slash?, :separator_dash?], :time_zone, :scalar_year], :handle_generic),
|
153
156
|
Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day], :handle_rdn_rmn_sd),
|
154
157
|
Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :scalar_year], :handle_rdn_rmn_sd_sy),
|
155
158
|
Handler.new([:repeater_day_name, :repeater_month_name, :ordinal_day], :handle_rdn_rmn_od),
|
159
|
+
Handler.new([:repeater_day_name, :repeater_month_name, :ordinal_day, :scalar_year], :handle_rdn_rmn_od_sy),
|
156
160
|
Handler.new([:repeater_day_name, :repeater_month_name, :scalar_day, :separator_at?, 'time?'], :handle_rdn_rmn_sd),
|
157
161
|
Handler.new([:repeater_day_name, :repeater_month_name, :ordinal_day, :separator_at?, 'time?'], :handle_rdn_rmn_od),
|
158
162
|
Handler.new([:repeater_day_name, :ordinal_day, :separator_at?, 'time?'], :handle_rdn_od),
|
159
|
-
Handler.new([:scalar_year, :
|
163
|
+
Handler.new([:scalar_year, [:separator_slash, :separator_dash], :scalar_month, [:separator_slash, :separator_dash], :scalar_day, :repeater_time, :time_zone], :handle_generic),
|
164
|
+
Handler.new([:ordinal_day], :handle_generic),
|
160
165
|
Handler.new([:repeater_month_name, :scalar_day, :scalar_year], :handle_rmn_sd_sy),
|
161
166
|
Handler.new([:repeater_month_name, :ordinal_day, :scalar_year], :handle_rmn_od_sy),
|
162
167
|
Handler.new([:repeater_month_name, :scalar_day, :scalar_year, :separator_at?, 'time?'], :handle_rmn_sd_sy),
|
163
168
|
Handler.new([:repeater_month_name, :ordinal_day, :scalar_year, :separator_at?, 'time?'], :handle_rmn_od_sy),
|
164
|
-
Handler.new([:repeater_month_name, :
|
169
|
+
Handler.new([:repeater_month_name, [:separator_slash?, :separator_dash?], :scalar_day, :separator_at?, 'time?'], :handle_rmn_sd),
|
165
170
|
Handler.new([:repeater_time, :repeater_day_portion?, :separator_on?, :repeater_month_name, :scalar_day], :handle_rmn_sd_on),
|
166
171
|
Handler.new([:repeater_month_name, :ordinal_day, :separator_at?, 'time?'], :handle_rmn_od),
|
167
172
|
Handler.new([:ordinal_day, :repeater_month_name, :scalar_year, :separator_at?, 'time?'], :handle_od_rmn_sy),
|
@@ -171,12 +176,12 @@ module Chronic
|
|
171
176
|
Handler.new([:repeater_time, :repeater_day_portion?, :separator_on?, :repeater_month_name, :ordinal_day], :handle_rmn_od_on),
|
172
177
|
Handler.new([:repeater_month_name, :scalar_year], :handle_rmn_sy),
|
173
178
|
Handler.new([:scalar_day, :repeater_month_name, :scalar_year, :separator_at?, 'time?'], :handle_sd_rmn_sy),
|
174
|
-
Handler.new([:scalar_day, :
|
175
|
-
Handler.new([:scalar_year, :
|
176
|
-
Handler.new([:scalar_year, :
|
177
|
-
Handler.new([:scalar_month, :
|
178
|
-
Handler.new([:scalar_day, :
|
179
|
-
Handler.new([:scalar_year, :
|
179
|
+
Handler.new([:scalar_day, [:separator_slash?, :separator_dash?], :repeater_month_name, :separator_at?, 'time?'], :handle_sd_rmn),
|
180
|
+
Handler.new([:scalar_year, [:separator_slash, :separator_dash], :scalar_month, [:separator_slash, :separator_dash], :scalar_day, :separator_at?, 'time?'], :handle_sy_sm_sd),
|
181
|
+
Handler.new([:scalar_year, [:separator_slash, :separator_dash], :scalar_month], :handle_sy_sm),
|
182
|
+
Handler.new([:scalar_month, [:separator_slash, :separator_dash], :scalar_year], :handle_sm_sy),
|
183
|
+
Handler.new([:scalar_day, [:separator_slash, :separator_dash], :repeater_month_name, [:separator_slash, :separator_dash], :scalar_year, :repeater_time?], :handle_sm_rmn_sy),
|
184
|
+
Handler.new([:scalar_year, [:separator_slash, :separator_dash], :scalar_month, [:separator_slash, :separator_dash], :scalar?, :time_zone], :handle_generic),
|
180
185
|
],
|
181
186
|
|
182
187
|
:anchor => [
|
@@ -199,10 +204,10 @@ module Chronic
|
|
199
204
|
}
|
200
205
|
|
201
206
|
endians = [
|
202
|
-
Handler.new([:scalar_month, :
|
203
|
-
Handler.new([:scalar_month, :
|
204
|
-
Handler.new([:scalar_day, :
|
205
|
-
Handler.new([:scalar_day, :
|
207
|
+
Handler.new([:scalar_month, [:separator_slash, :separator_dash], :scalar_day, [:separator_slash, :separator_dash], :scalar_year, :separator_at?, 'time?'], :handle_sm_sd_sy),
|
208
|
+
Handler.new([:scalar_month, [:separator_slash, :separator_dash], :scalar_day, :separator_at?, 'time?'], :handle_sm_sd),
|
209
|
+
Handler.new([:scalar_day, [:separator_slash, :separator_dash], :scalar_month, :separator_at?, 'time?'], :handle_sd_sm),
|
210
|
+
Handler.new([:scalar_day, [:separator_slash, :separator_dash], :scalar_month, [:separator_slash, :separator_dash], :scalar_year, :separator_at?, 'time?'], :handle_sd_sm_sy)
|
206
211
|
]
|
207
212
|
|
208
213
|
case endian = Array(options[:endian_precedence]).first
|
@@ -220,7 +225,7 @@ module Chronic
|
|
220
225
|
def tokenize(text, options)
|
221
226
|
text = pre_normalize(text)
|
222
227
|
tokens = text.split(' ').map { |word| Token.new(word) }
|
223
|
-
[Repeater, Grabber, Pointer, Scalar, Ordinal, Separator, TimeZone].each do |tok|
|
228
|
+
[Repeater, Grabber, Pointer, Scalar, Ordinal, Separator, Sign, TimeZone].each do |tok|
|
224
229
|
tok.scan(tokens, options)
|
225
230
|
end
|
226
231
|
tokens.select { |token| token.tagged? }
|
@@ -245,7 +250,7 @@ module Chronic
|
|
245
250
|
|
246
251
|
definitions[:arrow].each do |handler|
|
247
252
|
if handler.match(tokens, definitions)
|
248
|
-
good_tokens = tokens.reject { |o| o.get_tag(SeparatorAt) || o.get_tag(
|
253
|
+
good_tokens = tokens.reject { |o| o.get_tag(SeparatorAt) || o.get_tag(SeparatorSlash) || o.get_tag(SeparatorDash) || o.get_tag(SeparatorComma) || o.get_tag(SeparatorAnd) }
|
249
254
|
return handler.invoke(:arrow, good_tokens, self, options)
|
250
255
|
end
|
251
256
|
end
|
data/lib/chronic/repeater.rb
CHANGED
@@ -10,32 +10,32 @@ module Chronic
|
|
10
10
|
# Returns an Array of tokens.
|
11
11
|
def self.scan(tokens, options)
|
12
12
|
tokens.each do |token|
|
13
|
-
if t = scan_for_season_names(token) then token.tag(t); next end
|
14
|
-
if t = scan_for_month_names(token) then token.tag(t); next end
|
15
|
-
if t = scan_for_day_names(token) then token.tag(t); next end
|
16
|
-
if t = scan_for_day_portions(token) then token.tag(t); next end
|
17
|
-
if t = scan_for_times(token) then token.tag(t); next end
|
18
|
-
if t = scan_for_units(token) then token.tag(t); next end
|
13
|
+
if t = scan_for_season_names(token, options) then token.tag(t); next end
|
14
|
+
if t = scan_for_month_names(token, options) then token.tag(t); next end
|
15
|
+
if t = scan_for_day_names(token, options) then token.tag(t); next end
|
16
|
+
if t = scan_for_day_portions(token, options) then token.tag(t); next end
|
17
|
+
if t = scan_for_times(token, options) then token.tag(t); next end
|
18
|
+
if t = scan_for_units(token, options) then token.tag(t); next end
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
# token - The Token object we want to scan.
|
23
23
|
#
|
24
24
|
# Returns a new Repeater object.
|
25
|
-
def self.scan_for_season_names(token)
|
25
|
+
def self.scan_for_season_names(token, options = {})
|
26
26
|
scan_for token, RepeaterSeasonName,
|
27
27
|
{
|
28
28
|
/^springs?$/ => :spring,
|
29
29
|
/^summers?$/ => :summer,
|
30
30
|
/^(autumn)|(fall)s?$/ => :autumn,
|
31
31
|
/^winters?$/ => :winter
|
32
|
-
}
|
32
|
+
}, options
|
33
33
|
end
|
34
34
|
|
35
35
|
# token - The Token object we want to scan.
|
36
36
|
#
|
37
37
|
# Returns a new Repeater object.
|
38
|
-
def self.scan_for_month_names(token)
|
38
|
+
def self.scan_for_month_names(token, options = {})
|
39
39
|
scan_for token, RepeaterMonthName,
|
40
40
|
{
|
41
41
|
/^jan[:\.]?(uary)?$/ => :january,
|
@@ -50,13 +50,13 @@ module Chronic
|
|
50
50
|
/^oct[:\.]?(ober)?$/ => :october,
|
51
51
|
/^nov[:\.]?(ember)?$/ => :november,
|
52
52
|
/^dec[:\.]?(ember)?$/ => :december
|
53
|
-
}
|
53
|
+
}, options
|
54
54
|
end
|
55
55
|
|
56
56
|
# token - The Token object we want to scan.
|
57
57
|
#
|
58
58
|
# Returns a new Repeater object.
|
59
|
-
def self.scan_for_day_names(token)
|
59
|
+
def self.scan_for_day_names(token, options = {})
|
60
60
|
scan_for token, RepeaterDayName,
|
61
61
|
{
|
62
62
|
/^m[ou]n(day)?$/ => :monday,
|
@@ -66,13 +66,13 @@ module Chronic
|
|
66
66
|
/^fr[iy](day)?$/ => :friday,
|
67
67
|
/^sat(t?[ue]rday)?$/ => :saturday,
|
68
68
|
/^su[nm](day)?$/ => :sunday
|
69
|
-
}
|
69
|
+
}, options
|
70
70
|
end
|
71
71
|
|
72
72
|
# token - The Token object we want to scan.
|
73
73
|
#
|
74
74
|
# Returns a new Repeater object.
|
75
|
-
def self.scan_for_day_portions(token)
|
75
|
+
def self.scan_for_day_portions(token, options = {})
|
76
76
|
scan_for token, RepeaterDayPortion,
|
77
77
|
{
|
78
78
|
/^ams?$/ => :am,
|
@@ -81,20 +81,20 @@ module Chronic
|
|
81
81
|
/^afternoons?$/ => :afternoon,
|
82
82
|
/^evenings?$/ => :evening,
|
83
83
|
/^(night|nite)s?$/ => :night
|
84
|
-
}
|
84
|
+
}, options
|
85
85
|
end
|
86
86
|
|
87
87
|
# token - The Token object we want to scan.
|
88
88
|
#
|
89
89
|
# Returns a new Repeater object.
|
90
|
-
def self.scan_for_times(token)
|
91
|
-
scan_for token, RepeaterTime, /^\d{1,2}(:?\d{1,2})?([\.:]?\d{1,2})
|
90
|
+
def self.scan_for_times(token, options = {})
|
91
|
+
scan_for token, RepeaterTime, /^\d{1,2}(:?\d{1,2})?([\.:]?\d{1,2}([\.:]\d{1,6})?)?$/, options
|
92
92
|
end
|
93
93
|
|
94
94
|
# token - The Token object we want to scan.
|
95
95
|
#
|
96
96
|
# Returns a new Repeater object.
|
97
|
-
def self.scan_for_units(token)
|
97
|
+
def self.scan_for_units(token, options = {})
|
98
98
|
{
|
99
99
|
/^years?$/ => :year,
|
100
100
|
/^seasons?$/ => :season,
|
@@ -114,7 +114,7 @@ module Chronic
|
|
114
114
|
if item =~ token.word
|
115
115
|
klass_name = 'Repeater' + symbol.to_s.capitalize
|
116
116
|
klass = Chronic.const_get(klass_name)
|
117
|
-
return klass.new(symbol)
|
117
|
+
return klass.new(symbol, options)
|
118
118
|
end
|
119
119
|
end
|
120
120
|
return nil
|
@@ -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
|
-
|
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
|
-
|
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,7 +26,7 @@ module Chronic
|
|
25
26
|
def next(pointer)
|
26
27
|
super
|
27
28
|
|
28
|
-
|
29
|
+
unless @current_span
|
29
30
|
now_seconds = @now - Chronic.construct(@now.year, @now.month, @now.day)
|
30
31
|
if now_seconds < @range.begin
|
31
32
|
case pointer
|
@@ -105,4 +106,4 @@ module Chronic
|
|
105
106
|
Chronic.construct(reference.year, reference.month, reference.day, hour_hand, minute_hand, second_hand)
|
106
107
|
end
|
107
108
|
end
|
108
|
-
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|