tickle 0.0.3 → 0.0.4

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.
@@ -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
- .Time.now
47
- 2010-04-22 17:11:52 -0400
48
-
49
- Tickle.parse('each day') #=> 2010-04-23 17:24:24 -0400
50
- Tickle.parse('every day') #=> 2010-04-23 17:24:24 -0400
51
- Tickle.parse('every week') #=> 2010-04-29 17:24:24 -0400
52
- Tickle.parse('every Month') #=> 2010-05-22 17:24:24 -0400
53
- Tickle.parse('every year') #=> 2011-04-22 17:24:24 -0400
54
- Tickle.parse('daily') #=> 2010-04-23 17:24:24 -0400
55
- Tickle.parse('weekly') #=> 2010-04-29 17:24:24 -0400
56
- Tickle.parse('monthly') #=> 2010-05-22 17:24:24 -0400
57
- Tickle.parse('yearly') #=> 2011-04-22 17:24:24 -0400
58
- Tickle.parse('every 3 days') #=> 2010-04-25 17:24:24 -0400
59
- Tickle.parse('every 3 weeks') #=> 2010-05-13 17:24:24 -0400
60
- Tickle.parse('every 3 months') #=> 2010-07-21 17:24:24 -0400
61
- Tickle.parse('every 3 years') #=> 2013-04-21 17:24:24 -0400
62
- Tickle.parse('every other day') #=> 2010-04-24 17:24:24 -0400
63
- Tickle.parse('every other week') #=> 2010-05-06 17:24:24 -0400
64
- Tickle.parse('every other month') #=> 2010-06-22 17:24:24 -0400
65
- Tickle.parse('every other year') #=> 2012-04-22 17:24:24 -0400
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-23 12:00:00 -0400
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-04-24 12:00:00 -0400
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
@@ -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.3
1
+ 0.0.4
@@ -0,0 +1 @@
1
+ GITFLOW_VERSION=0.0.4
@@ -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
- def days_in_month
31
- d,m,y = mday,month,year
32
- d += 1 while Date.valid_civil?(y,m,d)
33
- d - 1
34
- end
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
@@ -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 = 1 if token_types.same?([:day])
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 >= 15 ? Chronic.parse('15th day of next month') : Date.new(Date.today.year, Date.today.month, 15))
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 >= 15 && Date.today.month >= 6 ? Date.new(Date.today.year+1, 6, 15) : Date.new(Date.today.year, 6, 15))
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
@@ -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.scan_for_month_names(token)
8
- token = self.scan_for_day_names(token)
9
- token = self.scan_for_special_text(token)
10
- token = self.scan_for_units(token)
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
- /^mid(d)?le$/ => :middle}
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
- /^days?$/ => {:type => :day, :interval => 1, :start => :today},
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
@@ -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
- default_options.keys.include?(key) || raise(InvalidArgumentException, "#{key} is not a valid option key.")
11
+ raise(InvalidArgumentException, "#{key} is not a valid option key.") unless default_options.keys.include?(key)
12
12
  end
13
- Chronic.parse(specified_options[:start]) || raise(InvalidArgumentException, ':start specified is not a valid datetime.') if specified_options[:start]
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 pre_normalize(text)
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(word)
71
- @word = word
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
@@ -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('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')
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
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{tickle}
8
- s.version = "0.0.3"
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-22}
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
- - 3
9
- version: 0.0.3
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-22 00:00:00 -04:00
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