chronic 0.1.0 → 0.2.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.
- data/History.txt +49 -0
- data/Manifest.txt +47 -0
- data/{README → README.txt} +37 -7
- data/Rakefile +19 -0
- data/lib/chronic/chronic.rb +6 -9
- data/lib/chronic/handlers.rb +104 -40
- data/lib/chronic/pointer.rb +3 -3
- data/lib/chronic/repeater.rb +9 -8
- data/lib/chronic/repeaters/repeater_day.rb +15 -8
- data/lib/chronic/repeaters/repeater_day_name.rb +15 -10
- data/lib/chronic/repeaters/repeater_day_portion.rb +8 -8
- data/lib/chronic/repeaters/repeater_fortnight.rb +4 -3
- data/lib/chronic/repeaters/repeater_hour.rb +7 -7
- data/lib/chronic/repeaters/repeater_minute.rb +33 -2
- data/lib/chronic/repeaters/repeater_month.rb +15 -8
- data/lib/chronic/repeaters/repeater_month_name.rb +20 -9
- data/lib/chronic/repeaters/repeater_second.rb +2 -0
- data/lib/chronic/repeaters/repeater_time.rb +11 -3
- data/lib/chronic/repeaters/repeater_week.rb +6 -0
- data/lib/chronic/repeaters/repeater_weekend.rb +49 -0
- data/lib/chronic/repeaters/repeater_year.rb +13 -10
- data/lib/chronic/scalar.rb +1 -1
- data/lib/chronic/time_zone.rb +22 -0
- data/lib/chronic.rb +103 -8
- data/lib/numerizer/numerizer.rb +103 -0
- data/test/{parse_numbers.rb → test_Numerizer.rb} +6 -8
- data/test/test_RepeaterWeekend.rb +75 -0
- data/test/test_Time.rb +50 -0
- data/test/test_parsing.rb +265 -145
- metadata +51 -23
|
@@ -4,24 +4,29 @@ class Chronic::RepeaterDayName < Chronic::Repeater #:nodoc:
|
|
|
4
4
|
def next(pointer)
|
|
5
5
|
super
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
direction = pointer == :future ? 1 : -1
|
|
8
|
+
|
|
9
|
+
if !@current_day_start
|
|
10
|
+
@current_day_start = Time.construct(@now.year, @now.month, @now.day)
|
|
11
|
+
@current_day_start += direction * DAY_SECONDS
|
|
12
|
+
|
|
10
13
|
day_num = symbol_to_number(@type)
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
|
|
15
|
+
while @current_day_start.wday != day_num
|
|
16
|
+
@current_day_start += direction * DAY_SECONDS
|
|
13
17
|
end
|
|
14
18
|
else
|
|
15
|
-
@
|
|
19
|
+
@current_day_start += direction * 7 * DAY_SECONDS
|
|
16
20
|
end
|
|
17
|
-
|
|
18
|
-
Chronic::Span.new(
|
|
21
|
+
|
|
22
|
+
Chronic::Span.new(@current_day_start, @current_day_start + DAY_SECONDS)
|
|
19
23
|
end
|
|
20
24
|
|
|
21
25
|
def this(pointer = :future)
|
|
22
26
|
super
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
pointer = :future if pointer == :none
|
|
29
|
+
self.next(pointer)
|
|
25
30
|
end
|
|
26
31
|
|
|
27
32
|
def width
|
|
@@ -29,7 +34,7 @@ class Chronic::RepeaterDayName < Chronic::Repeater #:nodoc:
|
|
|
29
34
|
end
|
|
30
35
|
|
|
31
36
|
def to_s
|
|
32
|
-
super << '-
|
|
37
|
+
super << '-dayname-' << @type.to_s
|
|
33
38
|
end
|
|
34
39
|
|
|
35
40
|
private
|
|
@@ -28,27 +28,27 @@ class Chronic::RepeaterDayPortion < Chronic::Repeater #:nodoc:
|
|
|
28
28
|
full_day = 60 * 60 * 24
|
|
29
29
|
|
|
30
30
|
if !@current_span
|
|
31
|
-
now_seconds = @now - Time.
|
|
31
|
+
now_seconds = @now - Time.construct(@now.year, @now.month, @now.day)
|
|
32
32
|
if now_seconds < @range.begin
|
|
33
33
|
case pointer
|
|
34
34
|
when :future
|
|
35
|
-
range_start = Time.
|
|
35
|
+
range_start = Time.construct(@now.year, @now.month, @now.day) + @range.begin
|
|
36
36
|
when :past
|
|
37
|
-
range_start = Time.
|
|
37
|
+
range_start = Time.construct(@now.year, @now.month, @now.day) - full_day + @range.begin
|
|
38
38
|
end
|
|
39
39
|
elsif now_seconds > @range.end
|
|
40
40
|
case pointer
|
|
41
41
|
when :future
|
|
42
|
-
range_start = Time.
|
|
42
|
+
range_start = Time.construct(@now.year, @now.month, @now.day) + full_day + @range.begin
|
|
43
43
|
when :past
|
|
44
|
-
range_start = Time.
|
|
44
|
+
range_start = Time.construct(@now.year, @now.month, @now.day) + @range.begin
|
|
45
45
|
end
|
|
46
46
|
else
|
|
47
47
|
case pointer
|
|
48
48
|
when :future
|
|
49
|
-
range_start = Time.
|
|
49
|
+
range_start = Time.construct(@now.year, @now.month, @now.day) + full_day + @range.begin
|
|
50
50
|
when :past
|
|
51
|
-
range_start = Time.
|
|
51
|
+
range_start = Time.construct(@now.year, @now.month, @now.day) - full_day + @range.begin
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
@@ -66,7 +66,7 @@ class Chronic::RepeaterDayPortion < Chronic::Repeater #:nodoc:
|
|
|
66
66
|
def this(context = :future)
|
|
67
67
|
super
|
|
68
68
|
|
|
69
|
-
range_start = Time.
|
|
69
|
+
range_start = Time.construct(@now.year, @now.month, @now.day) + @range.begin
|
|
70
70
|
@current_span = Chronic::Span.new(range_start, range_start + (@range.end - @range.begin))
|
|
71
71
|
end
|
|
72
72
|
|
|
@@ -29,9 +29,11 @@ class Chronic::RepeaterFortnight < Chronic::Repeater #:nodoc:
|
|
|
29
29
|
def this(pointer = :future)
|
|
30
30
|
super
|
|
31
31
|
|
|
32
|
+
pointer = :future if pointer == :none
|
|
33
|
+
|
|
32
34
|
case pointer
|
|
33
35
|
when :future
|
|
34
|
-
this_fortnight_start = Time.
|
|
36
|
+
this_fortnight_start = Time.construct(@now.year, @now.month, @now.day, @now.hour) + Chronic::RepeaterHour::HOUR_SECONDS
|
|
35
37
|
sunday_repeater = Chronic::RepeaterDayName.new(:sunday)
|
|
36
38
|
sunday_repeater.start = @now
|
|
37
39
|
sunday_repeater.this(:future)
|
|
@@ -39,10 +41,9 @@ class Chronic::RepeaterFortnight < Chronic::Repeater #:nodoc:
|
|
|
39
41
|
this_fortnight_end = this_sunday_span.begin
|
|
40
42
|
Chronic::Span.new(this_fortnight_start, this_fortnight_end)
|
|
41
43
|
when :past
|
|
42
|
-
this_fortnight_end = Time.
|
|
44
|
+
this_fortnight_end = Time.construct(@now.year, @now.month, @now.day, @now.hour)
|
|
43
45
|
sunday_repeater = Chronic::RepeaterDayName.new(:sunday)
|
|
44
46
|
sunday_repeater.start = @now
|
|
45
|
-
#sunday_repeater.next(:past)
|
|
46
47
|
last_sunday_span = sunday_repeater.next(:past)
|
|
47
48
|
this_fortnight_start = last_sunday_span.begin
|
|
48
49
|
Chronic::Span.new(this_fortnight_start, this_fortnight_end)
|
|
@@ -7,9 +7,9 @@ class Chronic::RepeaterHour < Chronic::Repeater #:nodoc:
|
|
|
7
7
|
if !@current_hour_start
|
|
8
8
|
case pointer
|
|
9
9
|
when :future
|
|
10
|
-
@current_hour_start = Time.
|
|
10
|
+
@current_hour_start = Time.construct(@now.year, @now.month, @now.day, @now.hour + 1)
|
|
11
11
|
when :past
|
|
12
|
-
@current_hour_start = Time.
|
|
12
|
+
@current_hour_start = Time.construct(@now.year, @now.month, @now.day, @now.hour - 1)
|
|
13
13
|
end
|
|
14
14
|
else
|
|
15
15
|
direction = pointer == :future ? 1 : -1
|
|
@@ -24,13 +24,13 @@ class Chronic::RepeaterHour < Chronic::Repeater #:nodoc:
|
|
|
24
24
|
|
|
25
25
|
case pointer
|
|
26
26
|
when :future
|
|
27
|
-
hour_start = Time.
|
|
28
|
-
hour_end = Time.
|
|
27
|
+
hour_start = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min + 1)
|
|
28
|
+
hour_end = Time.construct(@now.year, @now.month, @now.day, @now.hour + 1)
|
|
29
29
|
when :past
|
|
30
|
-
hour_start = Time.
|
|
31
|
-
hour_end = Time.
|
|
30
|
+
hour_start = Time.construct(@now.year, @now.month, @now.day, @now.hour)
|
|
31
|
+
hour_end = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
|
|
32
32
|
when :none
|
|
33
|
-
hour_start = Time.
|
|
33
|
+
hour_start = Time.construct(@now.year, @now.month, @now.day, @now.hour)
|
|
34
34
|
hour_end = hour_begin + HOUR_SECONDS
|
|
35
35
|
end
|
|
36
36
|
|
|
@@ -1,9 +1,40 @@
|
|
|
1
1
|
class Chronic::RepeaterMinute < Chronic::Repeater #:nodoc:
|
|
2
2
|
MINUTE_SECONDS = 60
|
|
3
3
|
|
|
4
|
+
def next(pointer = :future)
|
|
5
|
+
super
|
|
6
|
+
|
|
7
|
+
if !@current_minute_start
|
|
8
|
+
case pointer
|
|
9
|
+
when :future
|
|
10
|
+
@current_minute_start = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min + 1)
|
|
11
|
+
when :past
|
|
12
|
+
@current_minute_start = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min - 1)
|
|
13
|
+
end
|
|
14
|
+
else
|
|
15
|
+
direction = pointer == :future ? 1 : -1
|
|
16
|
+
@current_minute_start += direction * MINUTE_SECONDS
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
Chronic::Span.new(@current_minute_start, @current_minute_start + MINUTE_SECONDS)
|
|
20
|
+
end
|
|
21
|
+
|
|
4
22
|
def this(pointer = :future)
|
|
5
|
-
|
|
6
|
-
|
|
23
|
+
super
|
|
24
|
+
|
|
25
|
+
case pointer
|
|
26
|
+
when :future
|
|
27
|
+
minute_begin = @now
|
|
28
|
+
minute_end = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
|
|
29
|
+
when :past
|
|
30
|
+
minute_begin = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
|
|
31
|
+
minute_end = @now
|
|
32
|
+
when :none
|
|
33
|
+
minute_begin = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min)
|
|
34
|
+
minute_end = Time.construct(@now.year, @now.month, @now.day, @now.hour, @now.min) + MINUTE_SECONDS
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
Chronic::Span.new(minute_begin, minute_end)
|
|
7
38
|
end
|
|
8
39
|
|
|
9
40
|
def offset(span, amount, pointer)
|
|
@@ -6,12 +6,12 @@ class Chronic::RepeaterMonth < Chronic::Repeater #:nodoc:
|
|
|
6
6
|
super
|
|
7
7
|
|
|
8
8
|
if !@current_month_start
|
|
9
|
-
@current_month_start = offset_by(Time.
|
|
9
|
+
@current_month_start = offset_by(Time.construct(@now.year, @now.month), 1, pointer)
|
|
10
10
|
else
|
|
11
|
-
@current_month_start = offset_by(Time.
|
|
11
|
+
@current_month_start = offset_by(Time.construct(@current_month_start.year, @current_month_start.month), 1, pointer)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
Chronic::Span.new(@current_month_start, Time.
|
|
14
|
+
Chronic::Span.new(@current_month_start, Time.construct(@current_month_start.year, @current_month_start.month + 1))
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def this(pointer = :future)
|
|
@@ -19,11 +19,14 @@ class Chronic::RepeaterMonth < Chronic::Repeater #:nodoc:
|
|
|
19
19
|
|
|
20
20
|
case pointer
|
|
21
21
|
when :future
|
|
22
|
-
month_start = Time.
|
|
23
|
-
month_end = self.offset_by(Time.
|
|
22
|
+
month_start = Time.construct(@now.year, @now.month, @now.day + 1)
|
|
23
|
+
month_end = self.offset_by(Time.construct(@now.year, @now.month), 1, :future)
|
|
24
24
|
when :past
|
|
25
|
-
month_start = Time.
|
|
26
|
-
month_end = Time.
|
|
25
|
+
month_start = Time.construct(@now.year, @now.month)
|
|
26
|
+
month_end = Time.construct(@now.year, @now.month, @now.day)
|
|
27
|
+
when :none
|
|
28
|
+
month_start = Time.construct(@now.year, @now.month)
|
|
29
|
+
month_end = self.offset_by(Time.construct(@now.year, @now.month), 1, :future)
|
|
27
30
|
end
|
|
28
31
|
|
|
29
32
|
Chronic::Span.new(month_start, month_end)
|
|
@@ -45,10 +48,14 @@ class Chronic::RepeaterMonth < Chronic::Repeater #:nodoc:
|
|
|
45
48
|
new_year += 1
|
|
46
49
|
new_month -= YEAR_MONTHS
|
|
47
50
|
end
|
|
48
|
-
Time.
|
|
51
|
+
Time.construct(new_year, new_month, time.day, time.hour, time.min, time.sec)
|
|
49
52
|
end
|
|
50
53
|
|
|
51
54
|
def width
|
|
52
55
|
MONTH_SECONDS
|
|
53
56
|
end
|
|
57
|
+
|
|
58
|
+
def to_s
|
|
59
|
+
super << '-month'
|
|
60
|
+
end
|
|
54
61
|
end
|
|
@@ -9,24 +9,30 @@ class Chronic::RepeaterMonthName < Chronic::Repeater #:nodoc:
|
|
|
9
9
|
case pointer
|
|
10
10
|
when :future
|
|
11
11
|
if @now.month < target_month
|
|
12
|
-
@current_month_begin = Time.
|
|
12
|
+
@current_month_begin = Time.construct(@now.year, target_month)
|
|
13
13
|
else @now.month > target_month
|
|
14
|
-
@current_month_begin = Time.
|
|
14
|
+
@current_month_begin = Time.construct(@now.year + 1, target_month)
|
|
15
|
+
end
|
|
16
|
+
when :none
|
|
17
|
+
if @now.month <= target_month
|
|
18
|
+
@current_month_begin = Time.construct(@now.year, target_month)
|
|
19
|
+
else @now.month > target_month
|
|
20
|
+
@current_month_begin = Time.construct(@now.year + 1, target_month)
|
|
15
21
|
end
|
|
16
22
|
when :past
|
|
17
23
|
if @now.month > target_month
|
|
18
|
-
@current_month_begin = Time.
|
|
24
|
+
@current_month_begin = Time.construct(@now.year, target_month)
|
|
19
25
|
else @now.month < target_month
|
|
20
|
-
@current_month_begin = Time.
|
|
26
|
+
@current_month_begin = Time.construct(@now.year - 1, target_month)
|
|
21
27
|
end
|
|
22
28
|
end
|
|
23
29
|
@current_month_begin || raise("Current month should be set by now")
|
|
24
30
|
else
|
|
25
31
|
case pointer
|
|
26
32
|
when :future
|
|
27
|
-
@current_month_begin = Time.
|
|
33
|
+
@current_month_begin = Time.construct(@current_month_begin.year + 1, @current_month_begin.month)
|
|
28
34
|
when :past
|
|
29
|
-
@current_month_begin = Time.
|
|
35
|
+
@current_month_begin = Time.construct(@current_month_begin.year - 1, @current_month_begin.month)
|
|
30
36
|
end
|
|
31
37
|
end
|
|
32
38
|
|
|
@@ -41,13 +47,18 @@ class Chronic::RepeaterMonthName < Chronic::Repeater #:nodoc:
|
|
|
41
47
|
next_month_month = cur_month_month + 1
|
|
42
48
|
end
|
|
43
49
|
|
|
44
|
-
Chronic::Span.new(@current_month_begin, Time.
|
|
50
|
+
Chronic::Span.new(@current_month_begin, Time.construct(next_month_year, next_month_month))
|
|
45
51
|
end
|
|
46
52
|
|
|
47
53
|
def this(pointer = :future)
|
|
48
54
|
super
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
case pointer
|
|
57
|
+
when :past
|
|
58
|
+
self.next(pointer)
|
|
59
|
+
when :future, :none
|
|
60
|
+
self.next(:none)
|
|
61
|
+
end
|
|
51
62
|
end
|
|
52
63
|
|
|
53
64
|
def width
|
|
@@ -59,7 +70,7 @@ class Chronic::RepeaterMonthName < Chronic::Repeater #:nodoc:
|
|
|
59
70
|
end
|
|
60
71
|
|
|
61
72
|
def to_s
|
|
62
|
-
super << '-
|
|
73
|
+
super << '-monthname-' << @type.to_s
|
|
63
74
|
end
|
|
64
75
|
|
|
65
76
|
private
|
|
@@ -25,7 +25,7 @@ class Chronic::RepeaterTime < Chronic::Repeater #:nodoc:
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def initialize(time, options = {})
|
|
28
|
-
t = time.
|
|
28
|
+
t = time.gsub(/\:/, '')
|
|
29
29
|
@type =
|
|
30
30
|
if (1..2) === t.size
|
|
31
31
|
Tick.new(t.to_i * 60 * 60, true)
|
|
@@ -34,8 +34,13 @@ class Chronic::RepeaterTime < Chronic::Repeater #:nodoc:
|
|
|
34
34
|
elsif t.size == 4
|
|
35
35
|
ambiguous = time =~ /:/ && t[0..0].to_i != 0 && t[0..1].to_i <= 12
|
|
36
36
|
Tick.new(t[0..1].to_i * 60 * 60 + t[2..3].to_i * 60, ambiguous)
|
|
37
|
+
elsif t.size == 5
|
|
38
|
+
Tick.new(t[0..0].to_i * 60 * 60 + t[1..2].to_i * 60 + t[3..4].to_i, true)
|
|
39
|
+
elsif t.size == 6
|
|
40
|
+
ambiguous = time =~ /:/ && t[0..0].to_i != 0 && t[0..1].to_i <= 12
|
|
41
|
+
Tick.new(t[0..1].to_i * 60 * 60 + t[2..3].to_i * 60 + t[4..5].to_i, ambiguous)
|
|
37
42
|
else
|
|
38
|
-
raise("Time cannot exceed
|
|
43
|
+
raise("Time cannot exceed six digits")
|
|
39
44
|
end
|
|
40
45
|
end
|
|
41
46
|
|
|
@@ -92,7 +97,10 @@ class Chronic::RepeaterTime < Chronic::Repeater #:nodoc:
|
|
|
92
97
|
end
|
|
93
98
|
|
|
94
99
|
def this(context = :future)
|
|
95
|
-
|
|
100
|
+
super
|
|
101
|
+
|
|
102
|
+
context = :future if context == :none
|
|
103
|
+
|
|
96
104
|
self.next(context)
|
|
97
105
|
end
|
|
98
106
|
|
|
@@ -44,6 +44,12 @@ class Chronic::RepeaterWeek < Chronic::Repeater #:nodoc:
|
|
|
44
44
|
last_sunday_span = sunday_repeater.next(:past)
|
|
45
45
|
this_week_start = last_sunday_span.begin
|
|
46
46
|
Chronic::Span.new(this_week_start, this_week_end)
|
|
47
|
+
when :none
|
|
48
|
+
sunday_repeater = Chronic::RepeaterDayName.new(:sunday)
|
|
49
|
+
sunday_repeater.start = @now
|
|
50
|
+
last_sunday_span = sunday_repeater.next(:past)
|
|
51
|
+
this_week_start = last_sunday_span.begin
|
|
52
|
+
Chronic::Span.new(this_week_start, this_week_start + WEEK_SECONDS)
|
|
47
53
|
end
|
|
48
54
|
end
|
|
49
55
|
|
|
@@ -1,6 +1,55 @@
|
|
|
1
1
|
class Chronic::RepeaterWeekend < Chronic::Repeater #:nodoc:
|
|
2
2
|
WEEKEND_SECONDS = 172_800 # (2 * 24 * 60 * 60)
|
|
3
3
|
|
|
4
|
+
def next(pointer)
|
|
5
|
+
super
|
|
6
|
+
|
|
7
|
+
if !@current_week_start
|
|
8
|
+
case pointer
|
|
9
|
+
when :future
|
|
10
|
+
saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
|
|
11
|
+
saturday_repeater.start = @now
|
|
12
|
+
next_saturday_span = saturday_repeater.next(:future)
|
|
13
|
+
@current_week_start = next_saturday_span.begin
|
|
14
|
+
when :past
|
|
15
|
+
saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
|
|
16
|
+
saturday_repeater.start = (@now + Chronic::RepeaterDay::DAY_SECONDS)
|
|
17
|
+
last_saturday_span = saturday_repeater.next(:past)
|
|
18
|
+
@current_week_start = last_saturday_span.begin
|
|
19
|
+
end
|
|
20
|
+
else
|
|
21
|
+
direction = pointer == :future ? 1 : -1
|
|
22
|
+
@current_week_start += direction * Chronic::RepeaterWeek::WEEK_SECONDS
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
Chronic::Span.new(@current_week_start, @current_week_start + WEEKEND_SECONDS)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def this(pointer = :future)
|
|
29
|
+
super
|
|
30
|
+
|
|
31
|
+
case pointer
|
|
32
|
+
when :future, :none
|
|
33
|
+
saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
|
|
34
|
+
saturday_repeater.start = @now
|
|
35
|
+
this_saturday_span = saturday_repeater.this(:future)
|
|
36
|
+
Chronic::Span.new(this_saturday_span.begin, this_saturday_span.begin + WEEKEND_SECONDS)
|
|
37
|
+
when :past
|
|
38
|
+
saturday_repeater = Chronic::RepeaterDayName.new(:saturday)
|
|
39
|
+
saturday_repeater.start = @now
|
|
40
|
+
last_saturday_span = saturday_repeater.this(:past)
|
|
41
|
+
Chronic::Span.new(last_saturday_span.begin, last_saturday_span.begin + WEEKEND_SECONDS)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def offset(span, amount, pointer)
|
|
46
|
+
direction = pointer == :future ? 1 : -1
|
|
47
|
+
weekend = Chronic::RepeaterWeekend.new(:weekend)
|
|
48
|
+
weekend.start = span.begin
|
|
49
|
+
start = weekend.next(pointer).begin + (amount - 1) * direction * Chronic::RepeaterWeek::WEEK_SECONDS
|
|
50
|
+
Chronic::Span.new(start, start + (span.end - span.begin))
|
|
51
|
+
end
|
|
52
|
+
|
|
4
53
|
def width
|
|
5
54
|
WEEKEND_SECONDS
|
|
6
55
|
end
|
|
@@ -6,16 +6,16 @@ class Chronic::RepeaterYear < Chronic::Repeater #:nodoc:
|
|
|
6
6
|
if !@current_year_start
|
|
7
7
|
case pointer
|
|
8
8
|
when :future
|
|
9
|
-
@current_year_start = Time.
|
|
9
|
+
@current_year_start = Time.construct(@now.year + 1)
|
|
10
10
|
when :past
|
|
11
|
-
@current_year_start = Time.
|
|
11
|
+
@current_year_start = Time.construct(@now.year - 1)
|
|
12
12
|
end
|
|
13
13
|
else
|
|
14
14
|
diff = pointer == :future ? 1 : -1
|
|
15
|
-
@current_year_start = Time.
|
|
15
|
+
@current_year_start = Time.construct(@current_year_start.year + diff)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
Chronic::Span.new(@current_year_start, Time.
|
|
18
|
+
Chronic::Span.new(@current_year_start, Time.construct(@current_year_start.year + 1))
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def this(pointer = :future)
|
|
@@ -23,11 +23,14 @@ class Chronic::RepeaterYear < Chronic::Repeater #:nodoc:
|
|
|
23
23
|
|
|
24
24
|
case pointer
|
|
25
25
|
when :future
|
|
26
|
-
this_year_start = Time.
|
|
27
|
-
this_year_end = Time.
|
|
26
|
+
this_year_start = Time.construct(@now.year, @now.month, @now.day) + Chronic::RepeaterDay::DAY_SECONDS
|
|
27
|
+
this_year_end = Time.construct(@now.year + 1, 1, 1)
|
|
28
28
|
when :past
|
|
29
|
-
this_year_start = Time.
|
|
30
|
-
this_year_end = Time.
|
|
29
|
+
this_year_start = Time.construct(@now.year, 1, 1)
|
|
30
|
+
this_year_end = Time.construct(@now.year, @now.month, @now.day)
|
|
31
|
+
when :none
|
|
32
|
+
this_year_start = Time.construct(@now.year, 1, 1)
|
|
33
|
+
this_year_end = Time.construct(@now.year + 1, 1, 1)
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
Chronic::Span.new(this_year_start, this_year_end)
|
|
@@ -37,10 +40,10 @@ class Chronic::RepeaterYear < Chronic::Repeater #:nodoc:
|
|
|
37
40
|
direction = pointer == :future ? 1 : -1
|
|
38
41
|
|
|
39
42
|
sb = span.begin
|
|
40
|
-
new_begin = Time.
|
|
43
|
+
new_begin = Time.construct(sb.year + (amount * direction), sb.month, sb.day, sb.hour, sb.min, sb.sec)
|
|
41
44
|
|
|
42
45
|
se = span.end
|
|
43
|
-
new_end = Time.
|
|
46
|
+
new_end = Time.construct(se.year + (amount * direction), se.month, se.day, se.hour, se.min, se.sec)
|
|
44
47
|
|
|
45
48
|
Chronic::Span.new(new_begin, new_end)
|
|
46
49
|
end
|
data/lib/chronic/scalar.rb
CHANGED
|
@@ -40,7 +40,7 @@ module Chronic
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def self.scan_for_years(token, post_token)
|
|
43
|
-
if token.word =~
|
|
43
|
+
if token.word =~ /^([1-9]\d)?\d\d?$/
|
|
44
44
|
unless post_token && %w{am pm morning afternoon evening night}.include?(post_token)
|
|
45
45
|
return ScalarYear.new(token.word.to_i)
|
|
46
46
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Chronic
|
|
2
|
+
class TimeZone < Tag #:nodoc:
|
|
3
|
+
def self.scan(tokens)
|
|
4
|
+
tokens.each_index do |i|
|
|
5
|
+
if t = self.scan_for_all(tokens[i]) then tokens[i].tag(t); next end
|
|
6
|
+
end
|
|
7
|
+
tokens
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.scan_for_all(token)
|
|
11
|
+
scanner = {/[PMCE][DS]T/i => :tz}
|
|
12
|
+
scanner.keys.each do |scanner_item|
|
|
13
|
+
return self.new(scanner[scanner_item]) if scanner_item =~ token.word
|
|
14
|
+
end
|
|
15
|
+
return nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_s
|
|
19
|
+
'timezone'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/chronic.rb
CHANGED
|
@@ -7,24 +7,119 @@
|
|
|
7
7
|
#
|
|
8
8
|
#=============================================================================
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
$:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed
|
|
11
11
|
|
|
12
12
|
require 'chronic/chronic'
|
|
13
13
|
require 'chronic/handlers'
|
|
14
|
+
|
|
15
|
+
require 'chronic/repeater'
|
|
16
|
+
require 'chronic/repeaters/repeater_year'
|
|
17
|
+
require 'chronic/repeaters/repeater_season'
|
|
18
|
+
require 'chronic/repeaters/repeater_season_name'
|
|
19
|
+
require 'chronic/repeaters/repeater_month'
|
|
20
|
+
require 'chronic/repeaters/repeater_month_name'
|
|
21
|
+
require 'chronic/repeaters/repeater_fortnight'
|
|
22
|
+
require 'chronic/repeaters/repeater_week'
|
|
23
|
+
require 'chronic/repeaters/repeater_weekend'
|
|
24
|
+
require 'chronic/repeaters/repeater_day'
|
|
25
|
+
require 'chronic/repeaters/repeater_day_name'
|
|
26
|
+
require 'chronic/repeaters/repeater_day_portion'
|
|
27
|
+
require 'chronic/repeaters/repeater_hour'
|
|
28
|
+
require 'chronic/repeaters/repeater_minute'
|
|
29
|
+
require 'chronic/repeaters/repeater_second'
|
|
30
|
+
require 'chronic/repeaters/repeater_time'
|
|
31
|
+
|
|
14
32
|
require 'chronic/grabber'
|
|
15
|
-
require 'chronic/ordinal'
|
|
16
33
|
require 'chronic/pointer'
|
|
17
34
|
require 'chronic/scalar'
|
|
35
|
+
require 'chronic/ordinal'
|
|
18
36
|
require 'chronic/separator'
|
|
37
|
+
require 'chronic/time_zone'
|
|
19
38
|
|
|
20
|
-
require '
|
|
21
|
-
Dir["#{File.dirname(__FILE__)}/chronic/repeaters/*.rb"].each do |file|
|
|
22
|
-
require file
|
|
23
|
-
end
|
|
39
|
+
require 'numerizer/numerizer'
|
|
24
40
|
|
|
25
41
|
module Chronic
|
|
26
|
-
|
|
42
|
+
VERSION = "0.2.2"
|
|
43
|
+
|
|
44
|
+
def self.debug; false; end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
alias p_orig p
|
|
48
|
+
|
|
49
|
+
def p(val)
|
|
50
|
+
p_orig val
|
|
51
|
+
puts
|
|
27
52
|
end
|
|
28
53
|
|
|
29
|
-
|
|
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
|
|
30
80
|
|
|
81
|
+
class Time
|
|
82
|
+
def self.construct(year, month = 1, day = 1, hour = 0, minute = 0, second = 0)
|
|
83
|
+
if second >= 60
|
|
84
|
+
minute += second / 60
|
|
85
|
+
second = second % 60
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
if minute >= 60
|
|
89
|
+
hour += minute / 60
|
|
90
|
+
minute = minute % 60
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if hour >= 24
|
|
94
|
+
day += hour / 24
|
|
95
|
+
hour = hour % 24
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# determine if there is a day overflow. this is complicated by our crappy calendar
|
|
99
|
+
# system (non-constant number of days per month)
|
|
100
|
+
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]
|
|
107
|
+
if day > days_this_month
|
|
108
|
+
month += day / days_this_month
|
|
109
|
+
day = day % days_this_month
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
if month > 12
|
|
114
|
+
if month % 12 == 0
|
|
115
|
+
year += (month - 12) / 12
|
|
116
|
+
month = 12
|
|
117
|
+
else
|
|
118
|
+
year += month / 12
|
|
119
|
+
month = month % 12
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
Time.local(year, month, day, hour, minute, second)
|
|
124
|
+
end
|
|
125
|
+
end
|