tickle 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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