chronic 0.4.1 → 0.6.5
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.
- data/.gemtest +0 -0
- data/.gitignore +5 -0
- data/.yardopts +3 -0
- data/HISTORY.md +75 -2
- data/README.md +10 -5
- data/Rakefile +12 -106
- data/chronic.gemspec +12 -78
- data/lib/chronic/chronic.rb +271 -101
- data/lib/chronic/grabber.rb +12 -3
- data/lib/chronic/handler.rb +90 -0
- data/lib/chronic/handlers.rb +247 -295
- data/lib/chronic/mini_date.rb +15 -5
- data/lib/chronic/numerizer.rb +3 -2
- data/lib/chronic/ordinal.rb +15 -4
- data/lib/chronic/pointer.rb +13 -5
- data/lib/chronic/repeater.rb +31 -15
- data/lib/chronic/repeaters/repeater_day.rb +6 -7
- data/lib/chronic/repeaters/repeater_day_name.rb +1 -2
- data/lib/chronic/repeaters/repeater_day_portion.rb +12 -13
- data/lib/chronic/repeaters/repeater_fortnight.rb +2 -3
- data/lib/chronic/repeaters/repeater_hour.rb +7 -8
- data/lib/chronic/repeaters/repeater_minute.rb +6 -7
- data/lib/chronic/repeaters/repeater_month.rb +22 -11
- data/lib/chronic/repeaters/repeater_month_name.rb +16 -24
- data/lib/chronic/repeaters/repeater_season.rb +10 -29
- data/lib/chronic/repeaters/repeater_season_name.rb +2 -4
- data/lib/chronic/repeaters/repeater_second.rb +0 -1
- data/lib/chronic/repeaters/repeater_time.rb +19 -20
- data/lib/chronic/repeaters/repeater_week.rb +0 -1
- data/lib/chronic/repeaters/repeater_weekday.rb +1 -2
- data/lib/chronic/repeaters/repeater_weekend.rb +0 -1
- data/lib/chronic/repeaters/repeater_year.rb +29 -18
- data/lib/chronic/scalar.rb +29 -1
- data/lib/chronic/season.rb +37 -0
- data/lib/chronic/separator.rb +24 -7
- data/lib/chronic/tag.rb +12 -1
- data/lib/chronic/time_zone.rb +14 -5
- data/lib/chronic/token.rb +14 -4
- data/lib/chronic.rb +66 -89
- data/test/helper.rb +1 -1
- data/test/test_Chronic.rb +97 -3
- data/test/test_DaylightSavings.rb +1 -1
- data/test/test_Handler.rb +1 -6
- data/test/test_MiniDate.rb +3 -3
- data/test/test_Numerizer.rb +1 -1
- data/test/test_RepeaterDayName.rb +1 -1
- data/test/test_RepeaterFortnight.rb +1 -1
- data/test/test_RepeaterHour.rb +1 -1
- data/test/test_RepeaterMinute.rb +1 -1
- data/test/test_RepeaterMonth.rb +5 -1
- data/test/test_RepeaterMonthName.rb +1 -1
- data/test/test_RepeaterSeason.rb +40 -0
- data/test/test_RepeaterTime.rb +1 -1
- data/test/test_RepeaterWeek.rb +1 -1
- data/test/test_RepeaterWeekday.rb +1 -1
- data/test/test_RepeaterWeekend.rb +1 -1
- data/test/test_RepeaterYear.rb +8 -1
- data/test/test_Span.rb +1 -1
- data/test/test_Token.rb +1 -1
- data/test/test_parsing.rb +228 -117
- metadata +30 -32
- data/Manifest.txt +0 -59
- data/benchmark/benchmark.rb +0 -13
- data/test/test_Time.rb +0 -49
data/lib/chronic/mini_date.rb
CHANGED
|
@@ -2,17 +2,27 @@ module Chronic
|
|
|
2
2
|
class MiniDate
|
|
3
3
|
attr_accessor :month, :day
|
|
4
4
|
|
|
5
|
+
def self.from_time(time)
|
|
6
|
+
new(time.month, time.day)
|
|
7
|
+
end
|
|
8
|
+
|
|
5
9
|
def initialize(month, day)
|
|
6
|
-
|
|
10
|
+
unless (1..12).include?(month)
|
|
11
|
+
raise ArgumentError, "1..12 are valid months"
|
|
12
|
+
end
|
|
13
|
+
|
|
7
14
|
@month = month
|
|
8
15
|
@day = day
|
|
9
16
|
end
|
|
10
17
|
|
|
11
18
|
def is_between?(md_start, md_end)
|
|
12
|
-
return false if (@month==md_start.month && @month==md_end.month &&
|
|
13
|
-
|
|
14
|
-
|
|
19
|
+
return false if (@month == md_start.month && @month == md_end.month) &&
|
|
20
|
+
(@day < md_start.day || @day > md_end.day)
|
|
21
|
+
return true if (@month == md_start.month && @day >= md_start.day) ||
|
|
22
|
+
(@month == md_end.month && @day <= md_end.day)
|
|
23
|
+
|
|
15
24
|
i = (md_start.month % 12) + 1
|
|
25
|
+
|
|
16
26
|
until i == md_end.month
|
|
17
27
|
return true if @month == i
|
|
18
28
|
i = (i % 12) + 1
|
|
@@ -22,7 +32,7 @@ module Chronic
|
|
|
22
32
|
end
|
|
23
33
|
|
|
24
34
|
def equals?(other)
|
|
25
|
-
@month == other.month and day == other.day
|
|
35
|
+
@month == other.month and @day == other.day
|
|
26
36
|
end
|
|
27
37
|
end
|
|
28
38
|
end
|
data/lib/chronic/numerizer.rb
CHANGED
|
@@ -107,14 +107,15 @@ module Chronic
|
|
|
107
107
|
|
|
108
108
|
def andition(string)
|
|
109
109
|
sc = StringScanner.new(string)
|
|
110
|
-
|
|
110
|
+
|
|
111
|
+
while sc.scan_until(/<num>(\d+)( | and )<num>(\d+)(?=[^\w]|$)/i)
|
|
111
112
|
if sc[2] =~ /and/ || sc[1].size > sc[3].size
|
|
112
113
|
string[(sc.pos - sc.matched_size)..(sc.pos-1)] = '<num>' + (sc[1].to_i + sc[3].to_i).to_s
|
|
113
114
|
sc.reset
|
|
114
115
|
end
|
|
115
116
|
end
|
|
116
117
|
end
|
|
117
|
-
end
|
|
118
118
|
|
|
119
|
+
end
|
|
119
120
|
end
|
|
120
121
|
end
|
data/lib/chronic/ordinal.rb
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
module Chronic
|
|
2
|
-
class Ordinal < Tag
|
|
2
|
+
class Ordinal < Tag
|
|
3
|
+
|
|
4
|
+
# Scan an Array of {Token}s and apply any necessary Ordinal tags to
|
|
5
|
+
# each token
|
|
6
|
+
#
|
|
7
|
+
# @param [Array<Token>] tokens Array of tokens to scan
|
|
8
|
+
# @param [Hash] options Options specified in {Chronic.parse}
|
|
9
|
+
# @return [Array] list of tokens
|
|
3
10
|
def self.scan(tokens, options)
|
|
4
|
-
tokens.
|
|
5
|
-
if t = scan_for_ordinals(
|
|
6
|
-
if t = scan_for_days(
|
|
11
|
+
tokens.each do |token|
|
|
12
|
+
if t = scan_for_ordinals(token) then token.tag(t) end
|
|
13
|
+
if t = scan_for_days(token) then token.tag(t) end
|
|
7
14
|
end
|
|
8
15
|
end
|
|
9
16
|
|
|
17
|
+
# @param [Token] token
|
|
18
|
+
# @return [Ordinal, nil]
|
|
10
19
|
def self.scan_for_ordinals(token)
|
|
11
20
|
Ordinal.new($1.to_i) if token.word =~ /^(\d*)(st|nd|rd|th)$/
|
|
12
21
|
end
|
|
13
22
|
|
|
23
|
+
# @param [Token] token
|
|
24
|
+
# @return [OrdinalDay, nil]
|
|
14
25
|
def self.scan_for_days(token)
|
|
15
26
|
if token.word =~ /^(\d*)(st|nd|rd|th)$/
|
|
16
27
|
unless $1.to_i > 31 || $1.to_i < 1
|
data/lib/chronic/pointer.rb
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
module Chronic
|
|
2
|
-
class Pointer < Tag
|
|
2
|
+
class Pointer < Tag
|
|
3
|
+
|
|
4
|
+
# Scan an Array of {Token}s and apply any necessary Pointer tags to
|
|
5
|
+
# each token
|
|
6
|
+
#
|
|
7
|
+
# @param [Array<Token>] tokens Array of tokens to scan
|
|
8
|
+
# @param [Hash] options Options specified in {Chronic.parse}
|
|
9
|
+
# @return [Array] list of tokens
|
|
3
10
|
def self.scan(tokens, options)
|
|
4
|
-
tokens.
|
|
5
|
-
if t = scan_for_all(
|
|
11
|
+
tokens.each do |token|
|
|
12
|
+
if t = scan_for_all(token) then token.tag(t) end
|
|
6
13
|
end
|
|
7
14
|
end
|
|
8
15
|
|
|
16
|
+
# @param [Token] token
|
|
17
|
+
# @return [Pointer, nil]
|
|
9
18
|
def self.scan_for_all(token)
|
|
10
19
|
scan_for token, self,
|
|
11
20
|
{
|
|
12
21
|
/\bpast\b/ => :past,
|
|
13
|
-
/\
|
|
14
|
-
/\bin\b/ => :future
|
|
22
|
+
/\b(?:future|in)\b/ => :future,
|
|
15
23
|
}
|
|
16
24
|
end
|
|
17
25
|
|
data/lib/chronic/repeater.rb
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
module Chronic
|
|
2
|
-
class Repeater < Tag
|
|
2
|
+
class Repeater < Tag
|
|
3
|
+
|
|
4
|
+
# Scan an Array of {Token}s and apply any necessary Repeater tags to
|
|
5
|
+
# each token
|
|
6
|
+
#
|
|
7
|
+
# @param [Array<Token>] tokens Array of tokens to scan
|
|
8
|
+
# @param [Hash] options Options specified in {Chronic.parse}
|
|
9
|
+
# @return [Array] list of tokens
|
|
3
10
|
def self.scan(tokens, options)
|
|
4
|
-
tokens.
|
|
5
|
-
if t = scan_for_season_names(
|
|
6
|
-
if t = scan_for_month_names(
|
|
7
|
-
if t = scan_for_day_names(
|
|
8
|
-
if t = scan_for_day_portions(
|
|
9
|
-
if t = scan_for_times(
|
|
10
|
-
if t = scan_for_units(
|
|
11
|
+
tokens.each do |token|
|
|
12
|
+
if t = scan_for_season_names(token) then token.tag(t); next end
|
|
13
|
+
if t = scan_for_month_names(token) then token.tag(t); next end
|
|
14
|
+
if t = scan_for_day_names(token) then token.tag(t); next end
|
|
15
|
+
if t = scan_for_day_portions(token) then token.tag(t); next end
|
|
16
|
+
if t = scan_for_times(token) then token.tag(t); next end
|
|
17
|
+
if t = scan_for_units(token) then token.tag(t); next end
|
|
11
18
|
end
|
|
12
19
|
end
|
|
13
20
|
|
|
21
|
+
# @param [Token] token
|
|
22
|
+
# @return [RepeaterSeasonName, nil]
|
|
14
23
|
def self.scan_for_season_names(token)
|
|
15
24
|
scan_for token, RepeaterSeasonName,
|
|
16
25
|
{
|
|
@@ -21,6 +30,8 @@ module Chronic
|
|
|
21
30
|
}
|
|
22
31
|
end
|
|
23
32
|
|
|
33
|
+
# @param [Token] token
|
|
34
|
+
# @return [RepeaterMonthName, nil]
|
|
24
35
|
def self.scan_for_month_names(token)
|
|
25
36
|
scan_for token, RepeaterMonthName,
|
|
26
37
|
{
|
|
@@ -39,22 +50,23 @@ module Chronic
|
|
|
39
50
|
}
|
|
40
51
|
end
|
|
41
52
|
|
|
53
|
+
# @param [Token] token
|
|
54
|
+
# @return [RepeaterDayName, nil]
|
|
42
55
|
def self.scan_for_day_names(token)
|
|
43
56
|
scan_for token, RepeaterDayName,
|
|
44
57
|
{
|
|
45
58
|
/^m[ou]n(day)?$/ => :monday,
|
|
46
|
-
/^t(ue|eu|oo|u|)s(day)?$/ => :tuesday,
|
|
47
|
-
/^
|
|
48
|
-
/^
|
|
49
|
-
/^wed$/ => :wednesday,
|
|
50
|
-
/^th(urs|ers)day$/ => :thursday,
|
|
51
|
-
/^thu(rs)?$/ => :thursday,
|
|
59
|
+
/^t(ue|eu|oo|u|)s?(day)?$/ => :tuesday,
|
|
60
|
+
/^we(d|dnes|nds|nns)(day)?$/ => :wednesday,
|
|
61
|
+
/^th(u(?:rs)?|ers)(day)?$/ => :thursday,
|
|
52
62
|
/^fr[iy](day)?$/ => :friday,
|
|
53
63
|
/^sat(t?[ue]rday)?$/ => :saturday,
|
|
54
64
|
/^su[nm](day)?$/ => :sunday
|
|
55
65
|
}
|
|
56
66
|
end
|
|
57
67
|
|
|
68
|
+
# @param [Token] token
|
|
69
|
+
# @return [RepeaterDayPortion, nil]
|
|
58
70
|
def self.scan_for_day_portions(token)
|
|
59
71
|
scan_for token, RepeaterDayPortion,
|
|
60
72
|
{
|
|
@@ -67,10 +79,14 @@ module Chronic
|
|
|
67
79
|
}
|
|
68
80
|
end
|
|
69
81
|
|
|
82
|
+
# @param [Token] token
|
|
83
|
+
# @return [RepeaterTime, nil]
|
|
70
84
|
def self.scan_for_times(token)
|
|
71
85
|
scan_for token, RepeaterTime, /^\d{1,2}(:?\d{2})?([\.:]?\d{2})?$/
|
|
72
86
|
end
|
|
73
87
|
|
|
88
|
+
# @param [Token] token
|
|
89
|
+
# @return [Repeater] A new instance of a subclass of Repeater
|
|
74
90
|
def self.scan_for_units(token)
|
|
75
91
|
{
|
|
76
92
|
/^years?$/ => :year,
|
|
@@ -100,7 +116,7 @@ module Chronic
|
|
|
100
116
|
|
|
101
117
|
# returns the width (in seconds or months) of this repeatable.
|
|
102
118
|
def width
|
|
103
|
-
raise("
|
|
119
|
+
raise("Repeater#width must be overridden in subclasses")
|
|
104
120
|
end
|
|
105
121
|
|
|
106
122
|
# returns the next occurance of this repeatable.
|
|
@@ -4,7 +4,6 @@ module Chronic
|
|
|
4
4
|
|
|
5
5
|
def initialize(type)
|
|
6
6
|
super
|
|
7
|
-
@current_day_start = nil
|
|
8
7
|
end
|
|
9
8
|
|
|
10
9
|
def next(pointer)
|
|
@@ -25,14 +24,14 @@ module Chronic
|
|
|
25
24
|
|
|
26
25
|
case pointer
|
|
27
26
|
when :future
|
|
28
|
-
day_begin =
|
|
29
|
-
day_end =
|
|
27
|
+
day_begin = Chronic.construct(@now.year, @now.month, @now.day, @now.hour)
|
|
28
|
+
day_end = Chronic.construct(@now.year, @now.month, @now.day) + DAY_SECONDS
|
|
30
29
|
when :past
|
|
31
|
-
day_begin =
|
|
32
|
-
day_end =
|
|
30
|
+
day_begin = Chronic.construct(@now.year, @now.month, @now.day)
|
|
31
|
+
day_end = Chronic.construct(@now.year, @now.month, @now.day, @now.hour)
|
|
33
32
|
when :none
|
|
34
|
-
day_begin =
|
|
35
|
-
day_end =
|
|
33
|
+
day_begin = Chronic.construct(@now.year, @now.month, @now.day)
|
|
34
|
+
day_end = Chronic.construct(@now.year, @now.month, @now.day) + DAY_SECONDS
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
Span.new(day_begin, day_end)
|
|
@@ -4,7 +4,6 @@ module Chronic
|
|
|
4
4
|
|
|
5
5
|
def initialize(type)
|
|
6
6
|
super
|
|
7
|
-
@current_day_start = nil
|
|
8
7
|
end
|
|
9
8
|
|
|
10
9
|
def next(pointer)
|
|
@@ -25,7 +24,7 @@ module Chronic
|
|
|
25
24
|
@current_date += direction * 7
|
|
26
25
|
end
|
|
27
26
|
next_date = @current_date.succ
|
|
28
|
-
Span.new(
|
|
27
|
+
Span.new(Chronic.construct(@current_date.year, @current_date.month, @current_date.day), Chronic.construct(next_date.year, next_date.month, next_date.day))
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
def this(pointer = :future)
|
|
@@ -3,15 +3,14 @@ module Chronic
|
|
|
3
3
|
PORTIONS = {
|
|
4
4
|
:am => 0..(12 * 60 * 60 - 1),
|
|
5
5
|
:pm => (12 * 60 * 60)..(24 * 60 * 60 - 1),
|
|
6
|
-
:morning => (6 * 60 * 60)..(12 * 60 * 60),
|
|
7
|
-
:afternoon =>(13 * 60 * 60)..(17 * 60 * 60), # 1pm-5pm,
|
|
8
|
-
:evening => (17 * 60 * 60)..(20 * 60 * 60),
|
|
9
|
-
:night =>(20 * 60 * 60)..(24 * 60 * 60), # 8pm-12pm
|
|
6
|
+
:morning => (6 * 60 * 60)..(12 * 60 * 60), # 6am-12am,
|
|
7
|
+
:afternoon => (13 * 60 * 60)..(17 * 60 * 60), # 1pm-5pm,
|
|
8
|
+
:evening => (17 * 60 * 60)..(20 * 60 * 60), # 5pm-8pm,
|
|
9
|
+
:night => (20 * 60 * 60)..(24 * 60 * 60), # 8pm-12pm
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
def initialize(type)
|
|
13
13
|
super
|
|
14
|
-
@current_span = nil
|
|
15
14
|
|
|
16
15
|
if type.kind_of? Integer
|
|
17
16
|
@range = (@type * 60 * 60)..((@type + 12) * 60 * 60)
|
|
@@ -29,27 +28,27 @@ module Chronic
|
|
|
29
28
|
full_day = 60 * 60 * 24
|
|
30
29
|
|
|
31
30
|
if !@current_span
|
|
32
|
-
now_seconds = @now -
|
|
31
|
+
now_seconds = @now - Chronic.construct(@now.year, @now.month, @now.day)
|
|
33
32
|
if now_seconds < @range.begin
|
|
34
33
|
case pointer
|
|
35
34
|
when :future
|
|
36
|
-
range_start =
|
|
35
|
+
range_start = Chronic.construct(@now.year, @now.month, @now.day) + @range.begin
|
|
37
36
|
when :past
|
|
38
|
-
range_start =
|
|
37
|
+
range_start = Chronic.construct(@now.year, @now.month, @now.day) - full_day + @range.begin
|
|
39
38
|
end
|
|
40
39
|
elsif now_seconds > @range.end
|
|
41
40
|
case pointer
|
|
42
41
|
when :future
|
|
43
|
-
range_start =
|
|
42
|
+
range_start = Chronic.construct(@now.year, @now.month, @now.day) + full_day + @range.begin
|
|
44
43
|
when :past
|
|
45
|
-
range_start =
|
|
44
|
+
range_start = Chronic.construct(@now.year, @now.month, @now.day) + @range.begin
|
|
46
45
|
end
|
|
47
46
|
else
|
|
48
47
|
case pointer
|
|
49
48
|
when :future
|
|
50
|
-
range_start =
|
|
49
|
+
range_start = Chronic.construct(@now.year, @now.month, @now.day) + full_day + @range.begin
|
|
51
50
|
when :past
|
|
52
|
-
range_start =
|
|
51
|
+
range_start = Chronic.construct(@now.year, @now.month, @now.day) - full_day + @range.begin
|
|
53
52
|
end
|
|
54
53
|
end
|
|
55
54
|
|
|
@@ -67,7 +66,7 @@ module Chronic
|
|
|
67
66
|
def this(context = :future)
|
|
68
67
|
super
|
|
69
68
|
|
|
70
|
-
range_start =
|
|
69
|
+
range_start = Chronic.construct(@now.year, @now.month, @now.day) + @range.begin
|
|
71
70
|
@current_span = Span.new(range_start, range_start + (@range.end - @range.begin))
|
|
72
71
|
end
|
|
73
72
|
|
|
@@ -4,7 +4,6 @@ module Chronic
|
|
|
4
4
|
|
|
5
5
|
def initialize(type)
|
|
6
6
|
super
|
|
7
|
-
@current_fortnight_start = nil
|
|
8
7
|
end
|
|
9
8
|
|
|
10
9
|
def next(pointer)
|
|
@@ -39,7 +38,7 @@ module Chronic
|
|
|
39
38
|
|
|
40
39
|
case pointer
|
|
41
40
|
when :future
|
|
42
|
-
this_fortnight_start =
|
|
41
|
+
this_fortnight_start = Chronic.construct(@now.year, @now.month, @now.day, @now.hour) + RepeaterHour::HOUR_SECONDS
|
|
43
42
|
sunday_repeater = RepeaterDayName.new(:sunday)
|
|
44
43
|
sunday_repeater.start = @now
|
|
45
44
|
sunday_repeater.this(:future)
|
|
@@ -47,7 +46,7 @@ module Chronic
|
|
|
47
46
|
this_fortnight_end = this_sunday_span.begin
|
|
48
47
|
Span.new(this_fortnight_start, this_fortnight_end)
|
|
49
48
|
when :past
|
|
50
|
-
this_fortnight_end =
|
|
49
|
+
this_fortnight_end = Chronic.construct(@now.year, @now.month, @now.day, @now.hour)
|
|
51
50
|
sunday_repeater = RepeaterDayName.new(:sunday)
|
|
52
51
|
sunday_repeater.start = @now
|
|
53
52
|
last_sunday_span = sunday_repeater.next(:past)
|
|
@@ -4,7 +4,6 @@ module Chronic
|
|
|
4
4
|
|
|
5
5
|
def initialize(type)
|
|
6
6
|
super
|
|
7
|
-
@current_hour_start = nil
|
|
8
7
|
end
|
|
9
8
|
|
|
10
9
|
def next(pointer)
|
|
@@ -13,9 +12,9 @@ module Chronic
|
|
|
13
12
|
if !@current_hour_start
|
|
14
13
|
case pointer
|
|
15
14
|
when :future
|
|
16
|
-
@current_hour_start =
|
|
15
|
+
@current_hour_start = Chronic.construct(@now.year, @now.month, @now.day, @now.hour + 1)
|
|
17
16
|
when :past
|
|
18
|
-
@current_hour_start =
|
|
17
|
+
@current_hour_start = Chronic.construct(@now.year, @now.month, @now.day, @now.hour - 1)
|
|
19
18
|
end
|
|
20
19
|
else
|
|
21
20
|
direction = pointer == :future ? 1 : -1
|
|
@@ -30,13 +29,13 @@ module Chronic
|
|
|
30
29
|
|
|
31
30
|
case pointer
|
|
32
31
|
when :future
|
|
33
|
-
hour_start =
|
|
34
|
-
hour_end =
|
|
32
|
+
hour_start = Chronic.construct(@now.year, @now.month, @now.day, @now.hour, @now.min + 1)
|
|
33
|
+
hour_end = Chronic.construct(@now.year, @now.month, @now.day, @now.hour + 1)
|
|
35
34
|
when :past
|
|
36
|
-
hour_start =
|
|
37
|
-
hour_end =
|
|
35
|
+
hour_start = Chronic.construct(@now.year, @now.month, @now.day, @now.hour)
|
|
36
|
+
hour_end = Chronic.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
|
|
38
37
|
when :none
|
|
39
|
-
hour_start =
|
|
38
|
+
hour_start = Chronic.construct(@now.year, @now.month, @now.day, @now.hour)
|
|
40
39
|
hour_end = hour_start + HOUR_SECONDS
|
|
41
40
|
end
|
|
42
41
|
|
|
@@ -4,7 +4,6 @@ module Chronic
|
|
|
4
4
|
|
|
5
5
|
def initialize(type)
|
|
6
6
|
super
|
|
7
|
-
@current_minute_start = nil
|
|
8
7
|
end
|
|
9
8
|
|
|
10
9
|
def next(pointer = :future)
|
|
@@ -13,9 +12,9 @@ module Chronic
|
|
|
13
12
|
if !@current_minute_start
|
|
14
13
|
case pointer
|
|
15
14
|
when :future
|
|
16
|
-
@current_minute_start =
|
|
15
|
+
@current_minute_start = Chronic.construct(@now.year, @now.month, @now.day, @now.hour, @now.min + 1)
|
|
17
16
|
when :past
|
|
18
|
-
@current_minute_start =
|
|
17
|
+
@current_minute_start = Chronic.construct(@now.year, @now.month, @now.day, @now.hour, @now.min - 1)
|
|
19
18
|
end
|
|
20
19
|
else
|
|
21
20
|
direction = pointer == :future ? 1 : -1
|
|
@@ -31,13 +30,13 @@ module Chronic
|
|
|
31
30
|
case pointer
|
|
32
31
|
when :future
|
|
33
32
|
minute_begin = @now
|
|
34
|
-
minute_end =
|
|
33
|
+
minute_end = Chronic.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
|
|
35
34
|
when :past
|
|
36
|
-
minute_begin =
|
|
35
|
+
minute_begin = Chronic.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
|
|
37
36
|
minute_end = @now
|
|
38
37
|
when :none
|
|
39
|
-
minute_begin =
|
|
40
|
-
minute_end =
|
|
38
|
+
minute_begin = Chronic.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
|
|
39
|
+
minute_end = Chronic.construct(@now.year, @now.month, @now.day, @now.hour, @now.min) + MINUTE_SECONDS
|
|
41
40
|
end
|
|
42
41
|
|
|
43
42
|
Span.new(minute_begin, minute_end)
|
|
@@ -2,22 +2,23 @@ module Chronic
|
|
|
2
2
|
class RepeaterMonth < Repeater #:nodoc:
|
|
3
3
|
MONTH_SECONDS = 2_592_000 # 30 * 24 * 60 * 60
|
|
4
4
|
YEAR_MONTHS = 12
|
|
5
|
+
MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
|
6
|
+
MONTH_DAYS_LEAP = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
|
5
7
|
|
|
6
8
|
def initialize(type)
|
|
7
9
|
super
|
|
8
|
-
@current_month_start = nil
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def next(pointer)
|
|
12
13
|
super
|
|
13
14
|
|
|
14
15
|
if !@current_month_start
|
|
15
|
-
@current_month_start = offset_by(
|
|
16
|
+
@current_month_start = offset_by(Chronic.construct(@now.year, @now.month), 1, pointer)
|
|
16
17
|
else
|
|
17
|
-
@current_month_start = offset_by(
|
|
18
|
+
@current_month_start = offset_by(Chronic.construct(@current_month_start.year, @current_month_start.month), 1, pointer)
|
|
18
19
|
end
|
|
19
20
|
|
|
20
|
-
Span.new(@current_month_start,
|
|
21
|
+
Span.new(@current_month_start, Chronic.construct(@current_month_start.year, @current_month_start.month + 1))
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def this(pointer = :future)
|
|
@@ -25,14 +26,14 @@ module Chronic
|
|
|
25
26
|
|
|
26
27
|
case pointer
|
|
27
28
|
when :future
|
|
28
|
-
month_start =
|
|
29
|
-
month_end = self.offset_by(
|
|
29
|
+
month_start = Chronic.construct(@now.year, @now.month, @now.day + 1)
|
|
30
|
+
month_end = self.offset_by(Chronic.construct(@now.year, @now.month), 1, :future)
|
|
30
31
|
when :past
|
|
31
|
-
month_start =
|
|
32
|
-
month_end =
|
|
32
|
+
month_start = Chronic.construct(@now.year, @now.month)
|
|
33
|
+
month_end = Chronic.construct(@now.year, @now.month, @now.day)
|
|
33
34
|
when :none
|
|
34
|
-
month_start =
|
|
35
|
-
month_end = self.offset_by(
|
|
35
|
+
month_start = Chronic.construct(@now.year, @now.month)
|
|
36
|
+
month_end = self.offset_by(Chronic.construct(@now.year, @now.month), 1, :future)
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
Span.new(month_start, month_end)
|
|
@@ -54,7 +55,11 @@ module Chronic
|
|
|
54
55
|
new_year += 1
|
|
55
56
|
new_month -= YEAR_MONTHS
|
|
56
57
|
end
|
|
57
|
-
|
|
58
|
+
|
|
59
|
+
days = month_days(new_year, new_month)
|
|
60
|
+
new_day = time.day > days ? days : time.day
|
|
61
|
+
|
|
62
|
+
Chronic.construct(new_year, new_month, new_day, time.hour, time.min, time.sec)
|
|
58
63
|
end
|
|
59
64
|
|
|
60
65
|
def width
|
|
@@ -64,5 +69,11 @@ module Chronic
|
|
|
64
69
|
def to_s
|
|
65
70
|
super << '-month'
|
|
66
71
|
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def month_days(year, month)
|
|
76
|
+
Date.leap?(year) ? MONTH_DAYS_LEAP[month - 1] : MONTH_DAYS[month - 1]
|
|
77
|
+
end
|
|
67
78
|
end
|
|
68
79
|
end
|
|
@@ -18,41 +18,39 @@ module Chronic
|
|
|
18
18
|
|
|
19
19
|
def initialize(type)
|
|
20
20
|
super
|
|
21
|
-
@current_month_begin = nil
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
def next(pointer)
|
|
25
24
|
super
|
|
26
25
|
|
|
27
26
|
if !@current_month_begin
|
|
28
|
-
target_month = symbol_to_number(@type)
|
|
29
27
|
case pointer
|
|
30
28
|
when :future
|
|
31
|
-
if @now.month <
|
|
32
|
-
@current_month_begin =
|
|
33
|
-
elsif @now.month >
|
|
34
|
-
@current_month_begin =
|
|
29
|
+
if @now.month < index
|
|
30
|
+
@current_month_begin = Chronic.construct(@now.year, index)
|
|
31
|
+
elsif @now.month > index
|
|
32
|
+
@current_month_begin = Chronic.construct(@now.year + 1, index)
|
|
35
33
|
end
|
|
36
34
|
when :none
|
|
37
|
-
if @now.month <=
|
|
38
|
-
@current_month_begin =
|
|
39
|
-
elsif @now.month >
|
|
40
|
-
@current_month_begin =
|
|
35
|
+
if @now.month <= index
|
|
36
|
+
@current_month_begin = Chronic.construct(@now.year, index)
|
|
37
|
+
elsif @now.month > index
|
|
38
|
+
@current_month_begin = Chronic.construct(@now.year + 1, index)
|
|
41
39
|
end
|
|
42
40
|
when :past
|
|
43
|
-
if @now.month >=
|
|
44
|
-
@current_month_begin =
|
|
45
|
-
elsif @now.month <
|
|
46
|
-
@current_month_begin =
|
|
41
|
+
if @now.month >= index
|
|
42
|
+
@current_month_begin = Chronic.construct(@now.year, index)
|
|
43
|
+
elsif @now.month < index
|
|
44
|
+
@current_month_begin = Chronic.construct(@now.year - 1, index)
|
|
47
45
|
end
|
|
48
46
|
end
|
|
49
47
|
@current_month_begin || raise("Current month should be set by now")
|
|
50
48
|
else
|
|
51
49
|
case pointer
|
|
52
50
|
when :future
|
|
53
|
-
@current_month_begin =
|
|
51
|
+
@current_month_begin = Chronic.construct(@current_month_begin.year + 1, @current_month_begin.month)
|
|
54
52
|
when :past
|
|
55
|
-
@current_month_begin =
|
|
53
|
+
@current_month_begin = Chronic.construct(@current_month_begin.year - 1, @current_month_begin.month)
|
|
56
54
|
end
|
|
57
55
|
end
|
|
58
56
|
|
|
@@ -67,7 +65,7 @@ module Chronic
|
|
|
67
65
|
next_month_month = cur_month_month + 1
|
|
68
66
|
end
|
|
69
67
|
|
|
70
|
-
Span.new(@current_month_begin,
|
|
68
|
+
Span.new(@current_month_begin, Chronic.construct(next_month_year, next_month_month))
|
|
71
69
|
end
|
|
72
70
|
|
|
73
71
|
def this(pointer = :future)
|
|
@@ -86,17 +84,11 @@ module Chronic
|
|
|
86
84
|
end
|
|
87
85
|
|
|
88
86
|
def index
|
|
89
|
-
|
|
87
|
+
@index ||= MONTHS[@type]
|
|
90
88
|
end
|
|
91
89
|
|
|
92
90
|
def to_s
|
|
93
91
|
super << '-monthname-' << @type.to_s
|
|
94
92
|
end
|
|
95
|
-
|
|
96
|
-
private
|
|
97
|
-
|
|
98
|
-
def symbol_to_number(sym)
|
|
99
|
-
MONTHS[sym] || raise("Invalid symbol specified")
|
|
100
|
-
end
|
|
101
93
|
end
|
|
102
94
|
end
|