tickle 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +32 -22
- data/SCENARIOS.rdoc +3 -0
- data/VERSION +1 -1
- data/git-flow-version +1 -0
- data/lib/tickle.rb +26 -9
- data/lib/tickle/handler.rb +30 -7
- data/lib/tickle/repeater.rb +44 -6
- data/lib/tickle/tickle.rb +49 -19
- data/test/git-flow-version +1 -0
- data/test/test_parsing.rb +55 -42
- data/tickle.gemspec +4 -2
- metadata +5 -3
data/README.rdoc
CHANGED
@@ -43,42 +43,52 @@ Tickle HEAVILY uses chronic for parsing both the event and the start date.
|
|
43
43
|
require 'rubygems'
|
44
44
|
require 'tickle'
|
45
45
|
|
46
|
-
|
47
|
-
2010-04-
|
48
|
-
|
49
|
-
Tickle.parse('each day') #=> 2010-04-
|
50
|
-
Tickle.parse('every day') #=> 2010-04-
|
51
|
-
Tickle.parse('every week') #=> 2010-
|
52
|
-
Tickle.parse('every Month') #=> 2010-05-
|
53
|
-
Tickle.parse('every year') #=> 2011-04-
|
54
|
-
Tickle.parse('daily') #=> 2010-04-
|
55
|
-
Tickle.parse('weekly') #=> 2010-
|
56
|
-
Tickle.parse('monthly') #=> 2010-05-
|
57
|
-
Tickle.parse('yearly') #=> 2011-04-
|
58
|
-
Tickle.parse('every 3 days') #=> 2010-04-
|
59
|
-
Tickle.parse('every 3 weeks') #=> 2010-05-
|
60
|
-
Tickle.parse('every 3 months') #=> 2010-07-
|
61
|
-
Tickle.parse('every 3 years') #=> 2013-04-
|
62
|
-
Tickle.parse('every other day') #=> 2010-04-
|
63
|
-
Tickle.parse('every other week') #=> 2010-05-
|
64
|
-
Tickle.parse('every other month') #=> 2010-06-
|
65
|
-
Tickle.parse('every other year') #=> 2012-04-
|
46
|
+
Time.now
|
47
|
+
2010-04-24 12:05:51 -0400
|
48
|
+
|
49
|
+
Tickle.parse('each day') #=> 2010-04-24 12:05:51 -0400
|
50
|
+
Tickle.parse('every day') #=> 2010-04-24 12:05:51 -0400
|
51
|
+
Tickle.parse('every week') #=> 2010-05-01 12:05:51 -0400
|
52
|
+
Tickle.parse('every Month') #=> 2010-05-24 12:05:51 -0400
|
53
|
+
Tickle.parse('every year') #=> 2011-04-24 12:05:51 -0400
|
54
|
+
Tickle.parse('daily') #=> 2010-04-24 12:05:51 -0400
|
55
|
+
Tickle.parse('weekly') #=> 2010-05-01 12:05:51 -0400
|
56
|
+
Tickle.parse('monthly') #=> 2010-05-24 12:05:51 -0400
|
57
|
+
Tickle.parse('yearly') #=> 2011-04-24 12:05:51 -0400
|
58
|
+
Tickle.parse('every 3 days') #=> 2010-04-27 12:05:51 -0400
|
59
|
+
Tickle.parse('every 3 weeks') #=> 2010-05-15 12:05:51 -0400
|
60
|
+
Tickle.parse('every 3 months') #=> 2010-07-23 12:05:51 -0400
|
61
|
+
Tickle.parse('every 3 years') #=> 2013-04-23 12:05:51 -0400
|
62
|
+
Tickle.parse('every other day') #=> 2010-04-26 12:05:51 -0400
|
63
|
+
Tickle.parse('every other week') #=> 2010-05-08 12:05:51 -0400
|
64
|
+
Tickle.parse('every other month') #=> 2010-06-24 12:05:51 -0400
|
65
|
+
Tickle.parse('every other year') #=> 2012-04-24 12:05:51 -0400
|
66
66
|
Tickle.parse('every other day starting May 1st') #=> 2010-05-01 12:00:00 -0400
|
67
67
|
Tickle.parse('every other week starting this Sunday') #=> 2010-04-25 12:00:00 -0400
|
68
68
|
Tickle.parse('every Monday') #=> 2010-04-26 12:00:00 -0400
|
69
69
|
Tickle.parse('every Wednesday') #=> 2010-04-28 12:00:00 -0400
|
70
|
-
Tickle.parse('every Friday') #=> 2010-04-
|
70
|
+
Tickle.parse('every Friday') #=> 2010-04-30 12:00:00 -0400
|
71
71
|
Tickle.parse('every May') #=> 2010-05-01 12:00:00 -0400
|
72
72
|
Tickle.parse('every june') #=> 2010-06-01 12:00:00 -0400
|
73
73
|
Tickle.parse('beginning of the week') #=> 2010-04-25 12:00:00 -0400
|
74
74
|
Tickle.parse('middle of the week') #=> 2010-04-28 12:00:00 -0400
|
75
|
-
Tickle.parse('end of the week') #=> 2010-
|
75
|
+
Tickle.parse('end of the week') #=> 2010-05-01 12:00:00 -0400
|
76
76
|
Tickle.parse('beginning of the month') #=> 2010-05-01 12:00:00 -0400
|
77
77
|
Tickle.parse('middle of the month') #=> 2010-05-15 12:00:00 -0400
|
78
78
|
Tickle.parse('end of the month') #=> 2010-04-30 00:00:00 -0400
|
79
79
|
Tickle.parse('beginning of the year') #=> 2011-01-01 12:00:00 -0500
|
80
80
|
Tickle.parse('middle of the year') #=> 2010-06-15 00:00:00 -0400
|
81
81
|
Tickle.parse('end of the year') #=> 2010-12-31 00:00:00 -0500
|
82
|
+
Tickle.parse('the 3rd of May') #=> 2010-05-03 12:00:00 -0400
|
83
|
+
Tickle.parse('the 3rd of February') #=> 2011-02-03 12:00:00 -0500
|
84
|
+
Tickle.parse('the 10th of the month') #=> 2010-05-10 12:00:00 -0400
|
85
|
+
Tickle.parse('the tenth of the month') #=> 2010-05-10 12:00:00 -0400
|
86
|
+
Tickle.parse('the first of the month') #=> 2010-05-01 12:00:00 -0400
|
87
|
+
Tickle.parse('the thirtieth') #=> 2010-04-30 12:00:00 -0400
|
88
|
+
Tickle.parse('the fifth') #=> 2010-05-05 12:00:00 -0400
|
89
|
+
Tickle.parse('the 3rd Sunday of May') #=> 2010-05-16 12:00:00 -0400
|
90
|
+
Tickle.parse('the 3rd Sunday of the month') #=> 2010-05-16 12:00:00 -0400
|
91
|
+
|
82
92
|
|
83
93
|
|
84
94
|
-- USING IN APP
|
data/SCENARIOS.rdoc
CHANGED
@@ -10,3 +10,6 @@ every November 15th => month found with number. interval = 365, start_date = Ch
|
|
10
10
|
every day => word 'day' found without a number. interval = 1. start_day = today
|
11
11
|
every week => word 'week' found without a number. interval = 7. start_day = today
|
12
12
|
every month => word 'month' found without a number. interval = 30. start_day = today
|
13
|
+
|
14
|
+
|
15
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.4
|
data/git-flow-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
GITFLOW_VERSION=0.0.4
|
data/lib/tickle.rb
CHANGED
@@ -18,24 +18,41 @@ require 'tickle/repeater'
|
|
18
18
|
|
19
19
|
module Tickle
|
20
20
|
VERSION = "0.0.3"
|
21
|
-
|
21
|
+
|
22
22
|
def self.debug; false; end
|
23
|
-
|
23
|
+
|
24
24
|
def self.dwrite(msg)
|
25
25
|
puts msg if Tickle.debug
|
26
26
|
end
|
27
|
+
|
28
|
+
def self.is_date(str)
|
29
|
+
begin
|
30
|
+
Date.parse(str.to_s)
|
31
|
+
return true
|
32
|
+
rescue Exception => e
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
end
|
27
36
|
end
|
28
37
|
|
29
|
-
class Date
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
38
|
+
class Date
|
39
|
+
def days_in_month
|
40
|
+
d,m,y = mday,month,year
|
41
|
+
d += 1 while Date.valid_civil?(y,m,d)
|
42
|
+
d - 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class String
|
47
|
+
def is_ordinal?
|
48
|
+
scanner = %w{first second third fourth fifth sixth seventh eighth ninth tenth eleventh twelfth thirteenth fourteenth fifteenth sixteenth seventieth eighteenth nineteenth twenty thirty thirtieth}
|
49
|
+
regex = /\b(\d*)(st|nd|rd|th)\b/
|
50
|
+
!(self =~ regex).nil? || scanner.include?(self.downcase)
|
51
|
+
end
|
35
52
|
end
|
36
53
|
|
37
54
|
class Array
|
38
55
|
def same?(y)
|
39
56
|
self.sort == y.sort
|
40
57
|
end
|
41
|
-
end
|
58
|
+
end
|
data/lib/tickle/handler.rb
CHANGED
@@ -4,23 +4,24 @@ module Tickle
|
|
4
4
|
def guess()
|
5
5
|
interval = guess_unit_types
|
6
6
|
interval ||= guess_weekday
|
7
|
-
interval ||= guess_weekday
|
8
7
|
interval ||= guess_month_names
|
9
8
|
interval ||= guess_number_and_unit
|
9
|
+
interval ||= guess_ordinal
|
10
|
+
interval ||= guess_ordinal_and_unit
|
10
11
|
interval ||= guess_special
|
11
12
|
|
12
13
|
# defines the next occurrence of this tickle if not set in a guess routine
|
13
14
|
@next ||= @start + (interval * 60 * 60 * 24) if interval
|
14
|
-
|
15
|
+
|
15
16
|
# check to see if the start date is > NOW and, if so, set the next occurrence = start
|
16
17
|
@next = @start if @start.to_time > Time.now
|
17
|
-
|
18
|
+
|
18
19
|
# return the next occurrence
|
19
20
|
return @next.to_time if interval
|
20
21
|
end
|
21
22
|
|
22
23
|
def guess_unit_types
|
23
|
-
interval =
|
24
|
+
interval = 0 if token_types.same?([:day])
|
24
25
|
interval = 7 if token_types.same?([:week])
|
25
26
|
interval = 30 if token_types.same?([:month])
|
26
27
|
interval = 365 if token_types.same?([:year])
|
@@ -51,6 +52,20 @@ module Tickle
|
|
51
52
|
interval
|
52
53
|
end
|
53
54
|
|
55
|
+
def guess_ordinal
|
56
|
+
if token_types.same?([:ordinal]) then interval = 365; @next = Chronic.parse("#{token_of_type(:ordinal).start} day in #{Date::MONTHNAMES[get_next_month(token_of_type(:ordinal).start)]}"); end
|
57
|
+
interval
|
58
|
+
end
|
59
|
+
|
60
|
+
def guess_ordinal_and_unit
|
61
|
+
parse_text = ''
|
62
|
+
if token_types.same?([:ordinal, :month_name]) then interval = 365; @next = Chronic.parse("#{token_of_type(:ordinal).original} day in #{token_of_type(:month_name).start.to_s}"); end
|
63
|
+
if token_types.same?([:ordinal, :month]) then interval = 365; @next = Chronic.parse("#{token_of_type(:ordinal).start} day in #{Date::MONTHNAMES[get_next_month(token_of_type(:ordinal).start)]}"); end
|
64
|
+
if token_types.same?([:ordinal, :weekday, :month_name]) then interval = 365; @next = Chronic.parse("#{token_of_type(:ordinal).original} #{token_of_type(:weekday).start.to_s} in #{token_of_type(:month_name).start.to_s}"); end
|
65
|
+
if token_types.same?([:ordinal, :weekday, :month]) then interval = 365; @next = Chronic.parse("#{token_of_type(:ordinal).original} #{token_of_type(:weekday).start.to_s} in #{Date::MONTHNAMES[get_next_month(token_of_type(:ordinal).start)]}"); end
|
66
|
+
interval
|
67
|
+
end
|
68
|
+
|
54
69
|
def guess_special
|
55
70
|
interval = guess_special_other
|
56
71
|
interval ||= guess_special_beginning
|
@@ -81,16 +96,16 @@ module Tickle
|
|
81
96
|
if token_types.same?([:special, :year]) && token_of_type(:special).start == :end then interval = 365; @start = Date.new(Date.today.year, 12, 31); end
|
82
97
|
interval
|
83
98
|
end
|
84
|
-
|
99
|
+
|
85
100
|
def guess_special_middle
|
86
101
|
if token_types.same?([:special, :week]) && token_of_type(:special).start == :middle then interval = 7; @start = Chronic.parse('Wednesday'); end
|
87
102
|
if token_types.same?([:special, :month]) && token_of_type(:special).start == :middle then
|
88
103
|
interval = 30;
|
89
|
-
@start = (Date.today.day
|
104
|
+
@start = (Date.today.day > 15 ? Chronic.parse('15th day of next month') : Date.new(Date.today.year, Date.today.month, 15))
|
90
105
|
end
|
91
106
|
if token_types.same?([:special, :year]) && token_of_type(:special).start == :middle then
|
92
107
|
interval = 365;
|
93
|
-
@start = (Date.today.day
|
108
|
+
@start = (Date.today.day > 15 && Date.today.month > 6 ? Date.new(Date.today.year+1, 6, 15) : Date.new(Date.today.year, 6, 15))
|
94
109
|
end
|
95
110
|
interval
|
96
111
|
end
|
@@ -99,5 +114,13 @@ module Tickle
|
|
99
114
|
@tokens.detect {|token| token.type == type}
|
100
115
|
end
|
101
116
|
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def get_next_month(ordinal)
|
121
|
+
ord_to_int = ordinal.gsub(/\b(\d*)(st|nd|rd|th)\b/,'\1').to_i
|
122
|
+
month = (ord_to_int < Date.today.day ? Date.today.month + 1 : Date.today.month)
|
123
|
+
end
|
124
|
+
|
102
125
|
end
|
103
126
|
end
|
data/lib/tickle/repeater.rb
CHANGED
@@ -4,10 +4,12 @@ class Tickle::Repeater < Chronic::Tag #:nodoc:
|
|
4
4
|
# for each token
|
5
5
|
tokens.each do |token|
|
6
6
|
token = self.scan_for_numbers(token)
|
7
|
-
token = self.
|
8
|
-
token = self.
|
9
|
-
token = self.
|
10
|
-
token = self.
|
7
|
+
token = self.scan_for_ordinal_names(token)
|
8
|
+
token = self.scan_for_ordinals(token)
|
9
|
+
token = self.scan_for_month_names(token) unless token.type
|
10
|
+
token = self.scan_for_day_names(token) unless token.type
|
11
|
+
token = self.scan_for_special_text(token) unless token.type
|
12
|
+
token = self.scan_for_units(token) unless token.type
|
11
13
|
end
|
12
14
|
tokens
|
13
15
|
end
|
@@ -18,6 +20,42 @@ class Tickle::Repeater < Chronic::Tag #:nodoc:
|
|
18
20
|
token
|
19
21
|
end
|
20
22
|
|
23
|
+
def self.scan_for_ordinal_names(token)
|
24
|
+
scanner = {/first/ => '1st',
|
25
|
+
/second/ => '2nd',
|
26
|
+
/third/ => '3rd',
|
27
|
+
/fourth/ => '4th',
|
28
|
+
/fifth/ => '5th',
|
29
|
+
/sixth/ => '6th',
|
30
|
+
/seventh/ => '7th',
|
31
|
+
/eighth/ => '8th',
|
32
|
+
/ninth/ => '9th',
|
33
|
+
/tenth/ => '10th',
|
34
|
+
/eleventh/ => '11th',
|
35
|
+
/twelfth/ => '12th',
|
36
|
+
/thirteenth/ => '13th',
|
37
|
+
/fourteenth/ => '14th',
|
38
|
+
/fifteenth/ => '15th',
|
39
|
+
/sixteenth/ => '16th',
|
40
|
+
/seventeenth/ => '17th',
|
41
|
+
/eighteenth/ => '18th',
|
42
|
+
/nineteenth/ => '19th',
|
43
|
+
/twenty/ => '20th',
|
44
|
+
/thirty/ => '30th',
|
45
|
+
/thirtieth/ => '30th',
|
46
|
+
}
|
47
|
+
scanner.keys.each do |scanner_item|
|
48
|
+
token.update(:ordinal, scanner[scanner_item], 365) if scanner_item =~ token.original
|
49
|
+
end
|
50
|
+
token
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.scan_for_ordinals(token)
|
54
|
+
regex = /\b(\d*)(st|nd|rd|th)\b/
|
55
|
+
token.update(:ordinal, token.original, 365) if !(token.original =~ regex).nil?
|
56
|
+
token
|
57
|
+
end
|
58
|
+
|
21
59
|
def self.scan_for_month_names(token)
|
22
60
|
scanner = {/^jan\.?(uary)?$/ => :january,
|
23
61
|
/^feb\.?(ruary)?$/ => :february,
|
@@ -59,7 +97,7 @@ class Tickle::Repeater < Chronic::Tag #:nodoc:
|
|
59
97
|
/^begin(ing|ning)?$/ => :beginning,
|
60
98
|
/^start$/ => :beginning,
|
61
99
|
/^end$/ => :end,
|
62
|
-
|
100
|
+
/^mid(d)?le$/ => :middle}
|
63
101
|
scanner.keys.each do |scanner_item|
|
64
102
|
token.update(:special, scanner[scanner_item], 7) if scanner_item =~ token.word
|
65
103
|
end
|
@@ -72,7 +110,7 @@ class Tickle::Repeater < Chronic::Tag #:nodoc:
|
|
72
110
|
/^fortnights?$/ => {:type => :fortnight, :interval => 365, :start => :today},
|
73
111
|
/^week(ly)?s?$/ => {:type => :week, :interval => 7, :start => :today},
|
74
112
|
/^weekends?$/ => {:type => :weekend, :interval => 7, :start => :saturday},
|
75
|
-
|
113
|
+
/^days?$/ => {:type => :day, :interval => 1, :start => :today},
|
76
114
|
/^daily?$/ => {:type => :day, :interval => 1, :start => :today}}
|
77
115
|
scanner.keys.each do |scanner_item|
|
78
116
|
if scanner_item =~ token.word
|
data/lib/tickle/tickle.rb
CHANGED
@@ -8,43 +8,39 @@ module Tickle
|
|
8
8
|
|
9
9
|
# ensure the specified options are valid
|
10
10
|
specified_options.keys.each do |key|
|
11
|
-
|
11
|
+
raise(InvalidArgumentException, "#{key} is not a valid option key.") unless default_options.keys.include?(key)
|
12
12
|
end
|
13
|
-
|
14
|
-
|
15
|
-
# remove every is specified
|
16
|
-
text = text.gsub(/^every\s\b/, '')
|
17
|
-
|
18
|
-
# put the text into a normal format to ease scanning using Chronic
|
19
|
-
text = pre_normalize(text)
|
20
|
-
text = Chronic.pre_normalize(text)
|
21
|
-
text = numericize_ordinals(text)
|
13
|
+
raise(InvalidArgumentException, ':start specified is not a valid datetime.') unless (is_date(specified_options[:start]) || Chronic.parse(specified_options[:start])) if specified_options[:start]
|
22
14
|
|
23
15
|
# check to see if this event starts some other time and reset now
|
24
16
|
event, starting = text.split('starting')
|
25
17
|
@start = (Chronic.parse(starting) || options[:start])
|
26
18
|
@next = nil
|
27
19
|
|
20
|
+
# put the text into a normal format to ease scanning using Chronic
|
21
|
+
event = pre_tokenize(event)
|
22
|
+
|
28
23
|
# split into tokens
|
29
24
|
@tokens = base_tokenize(event)
|
30
25
|
|
26
|
+
# process each original word for implied word
|
27
|
+
post_tokenize
|
28
|
+
|
31
29
|
# scan the tokens with each token scanner
|
32
30
|
@tokens = Repeater.scan(@tokens)
|
33
31
|
|
34
32
|
# remove all tokens without a type
|
35
33
|
@tokens.reject! {|token| token.type.nil? }
|
36
34
|
|
37
|
-
# dwrite @tokens.inspect
|
38
|
-
|
39
35
|
return guess
|
40
36
|
end
|
41
37
|
|
42
38
|
# Normalize natural string removing prefix language
|
43
|
-
def
|
39
|
+
def pre_tokenize(text)
|
44
40
|
normalized_text = text.gsub(/^every\s\b/, '')
|
45
41
|
normalized_text = text.gsub(/^each\s\b/, '')
|
46
42
|
normalized_text = text.gsub(/^on the\s\b/, '')
|
47
|
-
normalized_text
|
43
|
+
normalized_text.downcase
|
48
44
|
end
|
49
45
|
|
50
46
|
# Split the text on spaces and convert each word into
|
@@ -53,11 +49,45 @@ module Tickle
|
|
53
49
|
text.split(' ').map { |word| Token.new(word) }
|
54
50
|
end
|
55
51
|
|
52
|
+
# normalizes each token
|
53
|
+
def post_tokenize
|
54
|
+
@tokens.each do |token|
|
55
|
+
token.word = normalize(token.original)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Clean up the specified input text by stripping unwanted characters,
|
60
|
+
# converting idioms to their canonical form, converting number words
|
61
|
+
# to numbers (three => 3), and converting ordinal words to numeric
|
62
|
+
# ordinals (third => 3rd)
|
63
|
+
def normalize(text) #:nodoc:
|
64
|
+
normalized_text = text.to_s.downcase
|
65
|
+
normalized_text = Numerizer.numerize(normalized_text)
|
66
|
+
normalized_text.gsub!(/['"\.]/, '')
|
67
|
+
normalized_text.gsub!(/([\/\-\,\@])/) { ' ' + $1 + ' ' }
|
68
|
+
normalized_text.gsub!(/\btoday\b/, 'this day')
|
69
|
+
normalized_text.gsub!(/\btomm?orr?ow\b/, 'next day')
|
70
|
+
normalized_text.gsub!(/\byesterday\b/, 'last day')
|
71
|
+
normalized_text.gsub!(/\bnoon\b/, '12:00')
|
72
|
+
normalized_text.gsub!(/\bmidnight\b/, '24:00')
|
73
|
+
normalized_text.gsub!(/\bbefore now\b/, 'past')
|
74
|
+
normalized_text.gsub!(/\bnow\b/, 'this second')
|
75
|
+
normalized_text.gsub!(/\b(ago|before)\b/, 'past')
|
76
|
+
normalized_text.gsub!(/\bthis past\b/, 'last')
|
77
|
+
normalized_text.gsub!(/\bthis last\b/, 'last')
|
78
|
+
normalized_text.gsub!(/\b(?:in|during) the (morning)\b/, '\1')
|
79
|
+
normalized_text.gsub!(/\b(?:in the|during the|at) (afternoon|evening|night)\b/, '\1')
|
80
|
+
normalized_text.gsub!(/\btonight\b/, 'this night')
|
81
|
+
normalized_text.gsub!(/(?=\w)([ap]m|oclock)\b/, ' \1')
|
82
|
+
normalized_text.gsub!(/\b(hence|after|from)\b/, 'future')
|
83
|
+
normalized_text = numericize_ordinals(normalized_text)
|
84
|
+
end
|
85
|
+
|
56
86
|
# Convert ordinal words to numeric ordinals (third => 3rd)
|
57
87
|
def numericize_ordinals(text) #:nodoc:
|
58
88
|
text = text.gsub(/\b(\d*)(st|nd|rd|th)\b/, '\1')
|
59
89
|
end
|
60
|
-
|
90
|
+
|
61
91
|
# Returns an array of types for all tokens
|
62
92
|
def token_types
|
63
93
|
@tokens.map(&:type)
|
@@ -65,11 +95,11 @@ module Tickle
|
|
65
95
|
end
|
66
96
|
|
67
97
|
class Token #:nodoc:
|
68
|
-
attr_accessor :word, :type, :interval, :start
|
98
|
+
attr_accessor :original, :word, :type, :interval, :start
|
69
99
|
|
70
|
-
def initialize(
|
71
|
-
@
|
72
|
-
@type = @interval = @start = nil
|
100
|
+
def initialize(original)
|
101
|
+
@original = original
|
102
|
+
@word = @type = @interval = @start = nil
|
73
103
|
end
|
74
104
|
|
75
105
|
def update(type, start=nil, interval=nil)
|
@@ -0,0 +1 @@
|
|
1
|
+
GITFLOW_VERSION=0.1.0
|
data/test/test_parsing.rb
CHANGED
@@ -11,49 +11,62 @@ class TestParsing < Test::Unit::TestCase
|
|
11
11
|
def test_parse_best_guess
|
12
12
|
puts "Time.now"
|
13
13
|
p Time.now
|
14
|
-
|
15
|
-
parse_now('each day')
|
16
|
-
|
17
|
-
parse_now('every day')
|
18
|
-
parse_now('every week')
|
19
|
-
parse_now('every Month')
|
20
|
-
parse_now('every year')
|
21
|
-
|
22
|
-
parse_now('daily')
|
23
|
-
parse_now('weekly')
|
24
|
-
parse_now('monthly')
|
25
|
-
parse_now('yearly')
|
26
|
-
|
27
|
-
parse_now('every 3 days')
|
28
|
-
parse_now('every 3 weeks')
|
29
|
-
parse_now('every 3 months')
|
30
|
-
parse_now('every 3 years')
|
31
|
-
|
32
|
-
parse_now('every other day')
|
33
|
-
parse_now('every other week')
|
34
|
-
parse_now('every other month')
|
35
|
-
parse_now('every other year')
|
36
|
-
parse_now('every other day starting May 1st')
|
37
|
-
parse_now('every other week starting this Sunday')
|
38
14
|
|
39
|
-
parse_now('
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
15
|
+
parse_now('each day')
|
16
|
+
|
17
|
+
parse_now('every day')
|
18
|
+
parse_now('every week')
|
19
|
+
parse_now('every Month')
|
20
|
+
parse_now('every year')
|
21
|
+
|
22
|
+
parse_now('daily')
|
23
|
+
parse_now('weekly')
|
24
|
+
parse_now('monthly')
|
25
|
+
parse_now('yearly')
|
26
|
+
|
27
|
+
parse_now('every 3 days')
|
28
|
+
parse_now('every 3 weeks')
|
29
|
+
parse_now('every 3 months')
|
30
|
+
parse_now('every 3 years')
|
31
|
+
|
32
|
+
parse_now('every other day')
|
33
|
+
parse_now('every other week')
|
34
|
+
parse_now('every other month')
|
35
|
+
parse_now('every other year')
|
36
|
+
parse_now('every other day starting May 1st')
|
37
|
+
parse_now('every other week starting this Sunday')
|
38
|
+
|
39
|
+
parse_now('every Monday')
|
40
|
+
parse_now('every Wednesday')
|
41
|
+
parse_now('every Friday')
|
42
|
+
|
43
|
+
parse_now('every May')
|
44
|
+
parse_now('every june')
|
45
|
+
|
46
|
+
parse_now('beginning of the week')
|
47
|
+
parse_now('middle of the week')
|
48
|
+
parse_now('end of the week')
|
49
|
+
|
50
|
+
parse_now('beginning of the month')
|
51
|
+
parse_now('middle of the month')
|
52
|
+
parse_now('end of the month')
|
53
|
+
|
54
|
+
parse_now('beginning of the year')
|
55
|
+
parse_now('middle of the year')
|
56
|
+
parse_now('end of the year')
|
57
|
+
|
58
|
+
parse_now('the 3rd of May')
|
59
|
+
parse_now('the 3rd of February', {:start => Date.new(2010, 03, 01).to_time})
|
60
|
+
|
61
|
+
parse_now('the 10th of the month')
|
62
|
+
parse_now('the tenth of the month')
|
63
|
+
|
64
|
+
parse_now('the first of the month')
|
65
|
+
parse_now('the thirtieth')
|
66
|
+
parse_now('the fifth', {:start => Date.new(2010, 03, 15)})
|
67
|
+
|
68
|
+
parse_now('the 3rd Sunday of May')
|
69
|
+
parse_now('the 3rd Sunday of the month')
|
57
70
|
end
|
58
71
|
|
59
72
|
def test_argument_validation
|
data/tickle.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{tickle}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Joshua Lippiner"]
|
12
|
-
s.date = %q{2010-04-
|
12
|
+
s.date = %q{2010-04-24}
|
13
13
|
s.description = %q{Tickle is a date/time helper gem to help parse natural language into a recurring pattern. Tickle is designed to be a compliment of Chronic and can interpret things such as "every 2 days, every Sunday, Sundays, Weekly, etc.}
|
14
14
|
s.email = %q{jlippiner@noctivity.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -25,11 +25,13 @@ Gem::Specification.new do |s|
|
|
25
25
|
"Rakefile",
|
26
26
|
"SCENARIOS.rdoc",
|
27
27
|
"VERSION",
|
28
|
+
"git-flow-version",
|
28
29
|
"lib/numerizer/numerizer.rb",
|
29
30
|
"lib/tickle.rb",
|
30
31
|
"lib/tickle/handler.rb",
|
31
32
|
"lib/tickle/repeater.rb",
|
32
33
|
"lib/tickle/tickle.rb",
|
34
|
+
"test/git-flow-version",
|
33
35
|
"test/helper.rb",
|
34
36
|
"test/test_parsing.rb",
|
35
37
|
"tickle.gemspec"
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 4
|
9
|
+
version: 0.0.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Joshua Lippiner
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-24 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -63,11 +63,13 @@ files:
|
|
63
63
|
- Rakefile
|
64
64
|
- SCENARIOS.rdoc
|
65
65
|
- VERSION
|
66
|
+
- git-flow-version
|
66
67
|
- lib/numerizer/numerizer.rb
|
67
68
|
- lib/tickle.rb
|
68
69
|
- lib/tickle/handler.rb
|
69
70
|
- lib/tickle/repeater.rb
|
70
71
|
- lib/tickle/tickle.rb
|
72
|
+
- test/git-flow-version
|
71
73
|
- test/helper.rb
|
72
74
|
- test/test_parsing.rb
|
73
75
|
- tickle.gemspec
|