lapluviosilla-tickle 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/.rvmrc +9 -0
- data/LICENSE +20 -0
- data/README.rdoc +436 -0
- data/Rakefile +55 -0
- data/SCENARIOS.rdoc +317 -0
- data/VERSION +1 -0
- data/git-flow-version +1 -0
- data/lapluviosilla-tickle.gemspec +65 -0
- data/lib/numerizer/numerizer.rb +103 -0
- data/lib/tickle/handler.rb +129 -0
- data/lib/tickle/repeater.rb +136 -0
- data/lib/tickle/tickle.rb +323 -0
- data/lib/tickle.rb +214 -0
- data/test/git-flow-version +1 -0
- data/test/helper.rb +11 -0
- data/test/test_parsing.rb +223 -0
- metadata +117 -0
data/SCENARIOS.rdoc
ADDED
@@ -0,0 +1,317 @@
|
|
1
|
+
=== EXAMPLES
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'tickle'
|
5
|
+
|
6
|
+
SIMPLE
|
7
|
+
Tickle.parse('day')
|
8
|
+
#=> {:next=>2010-05-10 20:57:36 -0400, :expression=>"day", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
9
|
+
|
10
|
+
Tickle.parse('day')
|
11
|
+
#=> {:next=>2010-05-10 20:57:36 -0400, :expression=>"day", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
12
|
+
|
13
|
+
Tickle.parse('week')
|
14
|
+
#=> {:next=>2010-05-16 20:57:36 -0400, :expression=>"week", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
15
|
+
|
16
|
+
Tickle.parse('month')
|
17
|
+
#=> {:next=>2010-06-09 20:57:36 -0400, :expression=>"month", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
18
|
+
|
19
|
+
Tickle.parse('year')
|
20
|
+
#=> {:next=>2011-05-09 20:57:36 -0400, :expression=>"year", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
21
|
+
|
22
|
+
Tickle.parse('daily')
|
23
|
+
#=> {:next=>2010-05-10 20:57:36 -0400, :expression=>"daily", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
24
|
+
|
25
|
+
Tickle.parse('weekly')
|
26
|
+
#=> {:next=>2010-05-16 20:57:36 -0400, :expression=>"weekly", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
27
|
+
|
28
|
+
Tickle.parse('monthly')
|
29
|
+
#=> {:next=>2010-06-09 20:57:36 -0400, :expression=>"monthly", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
30
|
+
|
31
|
+
Tickle.parse('yearly')
|
32
|
+
#=> {:next=>2011-05-09 20:57:36 -0400, :expression=>"yearly", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
33
|
+
|
34
|
+
Tickle.parse('3 days')
|
35
|
+
#=> {:next=>2010-05-12 20:57:36 -0400, :expression=>"3 days", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
36
|
+
|
37
|
+
Tickle.parse('3 weeks')
|
38
|
+
#=> {:next=>2010-05-30 20:57:36 -0400, :expression=>"3 weeks", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
39
|
+
|
40
|
+
Tickle.parse('3 months')
|
41
|
+
#=> {:next=>2010-08-09 20:57:36 -0400, :expression=>"3 months", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
42
|
+
|
43
|
+
Tickle.parse('3 years')
|
44
|
+
#=> {:next=>2013-05-09 20:57:36 -0400, :expression=>"3 years", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
45
|
+
|
46
|
+
Tickle.parse('other day')
|
47
|
+
#=> {:next=>2010-05-11 20:57:36 -0400, :expression=>"other day", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
48
|
+
|
49
|
+
Tickle.parse('other week')
|
50
|
+
#=> {:next=>2010-05-23 20:57:36 -0400, :expression=>"other week", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
51
|
+
|
52
|
+
Tickle.parse('other month')
|
53
|
+
#=> {:next=>2010-07-09 20:57:36 -0400, :expression=>"other month", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
54
|
+
|
55
|
+
Tickle.parse('other year')
|
56
|
+
#=> {:next=>2012-05-09 20:57:36 -0400, :expression=>"other year", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
57
|
+
|
58
|
+
Tickle.parse('Monday')
|
59
|
+
#=> {:next=>2010-05-10 12:00:00 -0400, :expression=>"monday", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
60
|
+
|
61
|
+
Tickle.parse('Wednesday')
|
62
|
+
#=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"wednesday", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
63
|
+
|
64
|
+
Tickle.parse('Friday')
|
65
|
+
#=> {:next=>2010-05-14 12:00:00 -0400, :expression=>"friday", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
66
|
+
|
67
|
+
Tickle.parse('February', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
68
|
+
#=> {:next=>2021-02-01 12:00:00 -0500, :expression=>"february", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
69
|
+
|
70
|
+
Tickle.parse('May', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
71
|
+
#=> {:next=>2020-05-01 12:00:00 -0400, :expression=>"may", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
72
|
+
|
73
|
+
Tickle.parse('june', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
74
|
+
#=> {:next=>2020-06-01 12:00:00 -0400, :expression=>"june", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
75
|
+
|
76
|
+
Tickle.parse('beginning of the week')
|
77
|
+
#=> {:next=>2010-05-16 12:00:00 -0400, :expression=>"beginning of the week", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
78
|
+
|
79
|
+
Tickle.parse('middle of the week')
|
80
|
+
#=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"middle of the week", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
81
|
+
|
82
|
+
Tickle.parse('end of the week')
|
83
|
+
#=> {:next=>2010-05-15 12:00:00 -0400, :expression=>"end of the week", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
84
|
+
|
85
|
+
Tickle.parse('beginning of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
86
|
+
#=> {:next=>2020-05-01 00:00:00 -0400, :expression=>"beginning of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
87
|
+
|
88
|
+
Tickle.parse('middle of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
89
|
+
#=> {:next=>2020-04-15 00:00:00 -0400, :expression=>"middle of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
90
|
+
|
91
|
+
Tickle.parse('end of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
92
|
+
#=> {:next=>2020-04-30 00:00:00 -0400, :expression=>"end of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
93
|
+
|
94
|
+
Tickle.parse('beginning of the year', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
95
|
+
#=> {:next=>2021-01-01 00:00:00 -0500, :expression=>"beginning of the year", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
96
|
+
|
97
|
+
Tickle.parse('middle of the year', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
98
|
+
#=> {:next=>2020-06-15 00:00:00 -0400, :expression=>"middle of the year", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
99
|
+
|
100
|
+
Tickle.parse('end of the year', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
101
|
+
#=> {:next=>2020-12-31 00:00:00 -0500, :expression=>"end of the year", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
102
|
+
|
103
|
+
Tickle.parse('the 3rd of May', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
104
|
+
#=> {:next=>2020-05-03 00:00:00 -0400, :expression=>"the 3rd of may", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
105
|
+
|
106
|
+
Tickle.parse('the 3rd of February', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
107
|
+
#=> {:next=>2021-02-03 00:00:00 -0500, :expression=>"the 3rd of february", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
108
|
+
|
109
|
+
Tickle.parse('the 3rd of February 2022', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
110
|
+
#=> {:next=>2022-02-03 00:00:00 -0500, :expression=>"the 3rd of february 2022", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
111
|
+
|
112
|
+
Tickle.parse('the 3rd of Feb 2022', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
113
|
+
#=> {:next=>2022-02-03 00:00:00 -0500, :expression=>"the 3rd of feb 2022", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
114
|
+
|
115
|
+
Tickle.parse('the 4th of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
116
|
+
#=> {:next=>2020-04-04 00:00:00 -0400, :expression=>"the 4th of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
117
|
+
|
118
|
+
Tickle.parse('the 10th of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
119
|
+
#=> {:next=>2020-04-10 00:00:00 -0400, :expression=>"the 10th of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
120
|
+
|
121
|
+
Tickle.parse('the tenth of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
122
|
+
#=> {:next=>2020-04-10 00:00:00 -0400, :expression=>"the tenth of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
123
|
+
|
124
|
+
Tickle.parse('first', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
125
|
+
#=> {:next=>2020-05-01 00:00:00 -0400, :expression=>"first", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
126
|
+
|
127
|
+
Tickle.parse('the first of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
128
|
+
#=> {:next=>2020-05-01 00:00:00 -0400, :expression=>"the first of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
129
|
+
|
130
|
+
Tickle.parse('the thirtieth', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
131
|
+
#=> {:next=>2020-04-30 00:00:00 -0400, :expression=>"the thirtieth", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
132
|
+
|
133
|
+
Tickle.parse('the fifth', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
134
|
+
#=> {:next=>2020-04-05 00:00:00 -0400, :expression=>"the fifth", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
135
|
+
|
136
|
+
Tickle.parse('the 1st Wednesday of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
137
|
+
#=> {:next=>2020-05-01 00:00:00 -0400, :expression=>"the 1st wednesday of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
138
|
+
|
139
|
+
Tickle.parse('the 3rd Sunday of May', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
140
|
+
#=> {:next=>2020-05-17 12:00:00 -0400, :expression=>"the 3rd sunday of may", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
141
|
+
|
142
|
+
Tickle.parse('the 3rd Sunday of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
143
|
+
#=> {:next=>2020-04-19 12:00:00 -0400, :expression=>"the 3rd sunday of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
144
|
+
|
145
|
+
Tickle.parse('the 23rd of June', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
146
|
+
#=> {:next=>2020-06-23 00:00:00 -0400, :expression=>"the 23rd of june", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
147
|
+
|
148
|
+
Tickle.parse('the twenty third of June', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
149
|
+
#=> {:next=>2020-06-23 00:00:00 -0400, :expression=>"the twenty third of june", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
150
|
+
|
151
|
+
Tickle.parse('the thirty first of July', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
152
|
+
#=> {:next=>2020-07-31 00:00:00 -0400, :expression=>"the thirty first of july", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
153
|
+
|
154
|
+
Tickle.parse('the twenty first', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
155
|
+
#=> {:next=>2020-04-21 00:00:00 -0400, :expression=>"the twenty first", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
156
|
+
|
157
|
+
Tickle.parse('the twenty first of the month', {:start=>#<Date: 2020-04-01 (4917881/2,0,2299161)>, :now=>#<Date: 2020-04-01 (4917881/2,0,2299161)>})
|
158
|
+
#=> {:next=>2020-04-21 00:00:00 -0400, :expression=>"the twenty first of the month", :starting=>2020-04-01 00:00:00 -0400, :until=>nil}
|
159
|
+
|
160
|
+
COMPLEX
|
161
|
+
Tickle.parse('starting today and ending one week from now')
|
162
|
+
#=> {:next=>2010-05-10 22:30:00 -0400, :expression=>"day", :starting=>2010-05-09 22:30:00 -0400, :until=>2010-05-16 20:57:35 -0400}
|
163
|
+
|
164
|
+
Tickle.parse('starting tomorrow and ending one week from now')
|
165
|
+
#=> {:next=>2010-05-10 12:00:00 -0400, :expression=>"day", :starting=>2010-05-10 12:00:00 -0400, :until=>2010-05-16 20:57:35 -0400}
|
166
|
+
|
167
|
+
Tickle.parse('starting Monday repeat every month')
|
168
|
+
#=> {:next=>2010-05-10 12:00:00 -0400, :expression=>"month", :starting=>2010-05-10 12:00:00 -0400, :until=>nil}
|
169
|
+
|
170
|
+
Tickle.parse('starting May 13th repeat every week')
|
171
|
+
#=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"week", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
|
172
|
+
|
173
|
+
Tickle.parse('starting May 13th repeat every other day')
|
174
|
+
#=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"other day", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
|
175
|
+
|
176
|
+
Tickle.parse('every other day starts May 13th')
|
177
|
+
#=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"other day", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
|
178
|
+
|
179
|
+
Tickle.parse('every other day starts May 13')
|
180
|
+
#=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"other day", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
|
181
|
+
|
182
|
+
Tickle.parse('every other day starting May 13th')
|
183
|
+
#=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"other day", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
|
184
|
+
|
185
|
+
Tickle.parse('every other day starting May 13')
|
186
|
+
#=> {:next=>2010-05-13 12:00:00 -0400, :expression=>"other day", :starting=>2010-05-13 12:00:00 -0400, :until=>nil}
|
187
|
+
|
188
|
+
Tickle.parse('every week starts this wednesday')
|
189
|
+
#=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"week", :starting=>2010-05-12 12:00:00 -0400, :until=>nil}
|
190
|
+
|
191
|
+
Tickle.parse('every week starting this wednesday')
|
192
|
+
#=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"week", :starting=>2010-05-12 12:00:00 -0400, :until=>nil}
|
193
|
+
|
194
|
+
Tickle.parse('every other day starting May 1st 2021')
|
195
|
+
#=> {:next=>2021-05-01 12:00:00 -0400, :expression=>"other day", :starting=>2021-05-01 12:00:00 -0400, :until=>nil}
|
196
|
+
|
197
|
+
Tickle.parse('every other day starting May 1 2021')
|
198
|
+
#=> {:next=>2021-05-01 12:00:00 -0400, :expression=>"other day", :starting=>2021-05-01 12:00:00 -0400, :until=>nil}
|
199
|
+
|
200
|
+
Tickle.parse('every other week starting this Sunday')
|
201
|
+
#=> {:next=>2010-05-16 12:00:00 -0400, :expression=>"other week", :starting=>2010-05-16 12:00:00 -0400, :until=>nil}
|
202
|
+
|
203
|
+
Tickle.parse('every week starting this wednesday until May 13th')
|
204
|
+
#=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"week", :starting=>2010-05-12 12:00:00 -0400, :until=>2010-05-13 12:00:00 -0400}
|
205
|
+
|
206
|
+
Tickle.parse('every week starting this wednesday ends May 13th')
|
207
|
+
#=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"week", :starting=>2010-05-12 12:00:00 -0400, :until=>2010-05-13 12:00:00 -0400}
|
208
|
+
|
209
|
+
Tickle.parse('every week starting this wednesday ending May 13th')
|
210
|
+
#=> {:next=>2010-05-12 12:00:00 -0400, :expression=>"week", :starting=>2010-05-12 12:00:00 -0400, :until=>2010-05-13 12:00:00 -0400}
|
211
|
+
|
212
|
+
|
213
|
+
OPTIONS HASH
|
214
|
+
Tickle.parse('May 1st 2020', {:next_only=>true})
|
215
|
+
#=> 2020-05-01 00:00:00 -0400
|
216
|
+
|
217
|
+
Tickle.parse('3 days', {:start=>2010-05-09 20:57:36 -0400})
|
218
|
+
#=> {:next=>2010-05-12 20:57:36 -0400, :expression=>"3 days", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
219
|
+
|
220
|
+
Tickle.parse('3 weeks', {:start=>2010-05-09 20:57:36 -0400})
|
221
|
+
#=> {:next=>2010-05-30 20:57:36 -0400, :expression=>"3 weeks", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
222
|
+
|
223
|
+
Tickle.parse('3 months', {:start=>2010-05-09 20:57:36 -0400})
|
224
|
+
#=> {:next=>2010-08-09 20:57:36 -0400, :expression=>"3 months", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
225
|
+
|
226
|
+
Tickle.parse('3 years', {:start=>2010-05-09 20:57:36 -0400})
|
227
|
+
#=> {:next=>2013-05-09 20:57:36 -0400, :expression=>"3 years", :starting=>2010-05-09 20:57:36 -0400, :until=>nil}
|
228
|
+
|
229
|
+
Tickle.parse('3 days', {:start=>2010-05-09 20:57:36 -0400, :until=>2010-10-09 00:00:00 -0400})
|
230
|
+
#=> {:next=>2010-05-12 20:57:36 -0400, :expression=>"3 days", :starting=>2010-05-09 20:57:36 -0400, :until=>2010-10-09 00:00:00 -0400}
|
231
|
+
|
232
|
+
Tickle.parse('3 weeks', {:start=>2010-05-09 20:57:36 -0400, :until=>2010-10-09 00:00:00 -0400})
|
233
|
+
#=> {:next=>2010-05-30 20:57:36 -0400, :expression=>"3 weeks", :starting=>2010-05-09 20:57:36 -0400, :until=>2010-10-09 00:00:00 -0400}
|
234
|
+
|
235
|
+
Tickle.parse('3 months', {:until=>2010-10-09 00:00:00 -0400})
|
236
|
+
#=> {:next=>2010-08-09 20:57:36 -0400, :expression=>"3 months", :starting=>2010-05-09 20:57:36 -0400, :until=>2010-10-09 00:00:00 -0400}
|
237
|
+
|
238
|
+
US HOLIDAYS
|
239
|
+
|
240
|
+
Tickle.parse('New Years Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
241
|
+
#=> {:next=>2021-01-01 12:00:00 -0500, :expression=>"january 1, 2021", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
242
|
+
|
243
|
+
Tickle.parse('Inauguration', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
244
|
+
#=> {:next=>2020-01-20 12:00:00 -0500, :expression=>"january 20", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
245
|
+
|
246
|
+
Tickle.parse('Martin Luther King Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
247
|
+
#=> {:next=>2020-01-20 12:00:00 -0500, :expression=>"third monday in january", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
248
|
+
|
249
|
+
Tickle.parse('MLK', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
250
|
+
#=> {:next=>2020-01-20 12:00:00 -0500, :expression=>"third monday in january", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
251
|
+
|
252
|
+
Tickle.parse('Presidents Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
253
|
+
#=> {:next=>2020-02-17 12:00:00 -0500, :expression=>"third monday in february", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
254
|
+
|
255
|
+
Tickle.parse('Memorial Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
256
|
+
#=> {:next=>2020-05-25 12:00:00 -0400, :expression=>"4th monday of may", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
257
|
+
|
258
|
+
Tickle.parse('Independence Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
259
|
+
#=> {:next=>2020-07-04 12:00:00 -0400, :expression=>"july 4, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
260
|
+
|
261
|
+
Tickle.parse('Labor Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
262
|
+
#=> {:next=>2020-09-07 12:00:00 -0400, :expression=>"first monday in september", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
263
|
+
|
264
|
+
Tickle.parse('Columbus Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
265
|
+
#=> {:next=>2020-10-12 12:00:00 -0400, :expression=>"second monday in october", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
266
|
+
|
267
|
+
Tickle.parse('Veterans Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
268
|
+
#=> {:next=>2020-11-11 12:00:00 -0500, :expression=>"november 11, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
269
|
+
|
270
|
+
Tickle.parse('Christmas', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
271
|
+
#=> {:next=>2020-12-25 12:00:00 -0500, :expression=>"december 25, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
272
|
+
|
273
|
+
Tickle.parse('Super Bowl Sunday', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
274
|
+
#=> {:next=>2020-02-02 12:00:00 -0500, :expression=>"first sunday in february", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
275
|
+
|
276
|
+
Tickle.parse('Groundhog Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
277
|
+
#=> {:next=>2020-02-02 12:00:00 -0500, :expression=>"february 2, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
278
|
+
|
279
|
+
Tickle.parse('Valentines Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
280
|
+
#=> {:next=>2020-02-14 12:00:00 -0500, :expression=>"february 14, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
281
|
+
|
282
|
+
Tickle.parse('Saint Patricks day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
283
|
+
#=> {:next=>2020-03-17 12:00:00 -0400, :expression=>"march 17, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
284
|
+
|
285
|
+
Tickle.parse('April Fools Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
286
|
+
#=> {:next=>2020-04-01 12:00:00 -0400, :expression=>"april 1, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
287
|
+
|
288
|
+
Tickle.parse('Earth Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
289
|
+
#=> {:next=>2020-04-22 12:00:00 -0400, :expression=>"april 22, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
290
|
+
|
291
|
+
Tickle.parse('Arbor Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
292
|
+
#=> {:next=>2020-04-24 12:00:00 -0400, :expression=>"fourth friday in april", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
293
|
+
|
294
|
+
Tickle.parse('Cinco De Mayo', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
295
|
+
#=> {:next=>2020-05-05 12:00:00 -0400, :expression=>"may 5, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
296
|
+
|
297
|
+
Tickle.parse('Mothers Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
298
|
+
#=> {:next=>2020-05-10 12:00:00 -0400, :expression=>"second sunday in may", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
299
|
+
|
300
|
+
Tickle.parse('Flag Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
301
|
+
#=> {:next=>2020-06-14 12:00:00 -0400, :expression=>"june 14, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
302
|
+
|
303
|
+
Tickle.parse('Fathers Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
304
|
+
#=> {:next=>2020-06-21 12:00:00 -0400, :expression=>"third sunday in june", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
305
|
+
|
306
|
+
Tickle.parse('Halloween', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
307
|
+
#=> {:next=>2020-10-31 12:00:00 -0400, :expression=>"october 31, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
308
|
+
|
309
|
+
Tickle.parse('Christmas Day', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
310
|
+
#=> {:next=>2020-12-25 12:00:00 -0500, :expression=>"december 25, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
311
|
+
|
312
|
+
Tickle.parse('Christmas Eve', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
313
|
+
#=> {:next=>2020-12-24 12:00:00 -0500, :expression=>"december 24, 2020", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
314
|
+
|
315
|
+
Tickle.parse('Kwanzaa', {:start=>#<Date: 2020-01-01 (4917699/2,0,2299161)>, :now=>#<Date: 2020-01-01 (4917699/2,0,2299161)>})
|
316
|
+
#=> {:next=>2021-01-01 12:00:00 -0500, :expression=>"january 1, 2021", :starting=>2020-01-01 00:00:00 -0500, :until=>nil}
|
317
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.8
|
data/git-flow-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
GITFLOW_VERSION=0.1.7
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{lapluviosilla-tickle}
|
8
|
+
s.version = "0.1.8"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Joshua Lippiner"]
|
12
|
+
s.date = %q{2010-08-23}
|
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
|
+
s.email = %q{jlippiner@noctivity.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
".rvmrc",
|
23
|
+
"LICENSE",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"SCENARIOS.rdoc",
|
27
|
+
"VERSION",
|
28
|
+
"git-flow-version",
|
29
|
+
"lapluviosilla-tickle.gemspec",
|
30
|
+
"lib/numerizer/numerizer.rb",
|
31
|
+
"lib/tickle.rb",
|
32
|
+
"lib/tickle/handler.rb",
|
33
|
+
"lib/tickle/repeater.rb",
|
34
|
+
"lib/tickle/tickle.rb",
|
35
|
+
"test/git-flow-version",
|
36
|
+
"test/helper.rb",
|
37
|
+
"test/test_parsing.rb"
|
38
|
+
]
|
39
|
+
s.homepage = %q{http://github.com/lapluviosilla/tickle}
|
40
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
41
|
+
s.require_paths = ["lib"]
|
42
|
+
s.rubygems_version = %q{1.3.7}
|
43
|
+
s.summary = %q{natural language parser for recurring events}
|
44
|
+
s.test_files = [
|
45
|
+
"test/helper.rb",
|
46
|
+
"test/test_parsing.rb"
|
47
|
+
]
|
48
|
+
|
49
|
+
if s.respond_to? :specification_version then
|
50
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
51
|
+
s.specification_version = 3
|
52
|
+
|
53
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
54
|
+
s.add_runtime_dependency(%q<chronic>, [">= 0.2.3"])
|
55
|
+
s.add_development_dependency(%q<shoulda>, [">= 2.10.3"])
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<chronic>, [">= 0.2.3"])
|
58
|
+
s.add_dependency(%q<shoulda>, [">= 2.10.3"])
|
59
|
+
end
|
60
|
+
else
|
61
|
+
s.add_dependency(%q<chronic>, [">= 0.2.3"])
|
62
|
+
s.add_dependency(%q<shoulda>, [">= 2.10.3"])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
class Numerizer
|
4
|
+
|
5
|
+
DIRECT_NUMS = [
|
6
|
+
['eleven', '11'],
|
7
|
+
['twelve', '12'],
|
8
|
+
['thirteen', '13'],
|
9
|
+
['fourteen', '14'],
|
10
|
+
['fifteen', '15'],
|
11
|
+
['sixteen', '16'],
|
12
|
+
['seventeen', '17'],
|
13
|
+
['eighteen', '18'],
|
14
|
+
['nineteen', '19'],
|
15
|
+
['ninteen', '19'], # Common mis-spelling
|
16
|
+
['zero', '0'],
|
17
|
+
['one', '1'],
|
18
|
+
['two', '2'],
|
19
|
+
['three', '3'],
|
20
|
+
['four(\W|$)', '4\1'], # The weird regex is so that it matches four but not fourty
|
21
|
+
['five', '5'],
|
22
|
+
['six(\W|$)', '6\1'],
|
23
|
+
['seven(\W|$)', '7\1'],
|
24
|
+
['eight(\W|$)', '8\1'],
|
25
|
+
['nine(\W|$)', '9\1'],
|
26
|
+
['ten', '10'],
|
27
|
+
['\ba[\b^$]', '1'] # doesn't make sense for an 'a' at the end to be a 1
|
28
|
+
]
|
29
|
+
|
30
|
+
TEN_PREFIXES = [ ['twenty', 20],
|
31
|
+
['thirty', 30],
|
32
|
+
['fourty', 40],
|
33
|
+
['fifty', 50],
|
34
|
+
['sixty', 60],
|
35
|
+
['seventy', 70],
|
36
|
+
['eighty', 80],
|
37
|
+
['ninety', 90]
|
38
|
+
]
|
39
|
+
|
40
|
+
BIG_PREFIXES = [ ['hundred', 100],
|
41
|
+
['thousand', 1000],
|
42
|
+
['million', 1_000_000],
|
43
|
+
['billion', 1_000_000_000],
|
44
|
+
['trillion', 1_000_000_000_000],
|
45
|
+
]
|
46
|
+
|
47
|
+
class << self
|
48
|
+
def numerize(string)
|
49
|
+
string = string.dup
|
50
|
+
|
51
|
+
# preprocess
|
52
|
+
string.gsub!(/ +|([^\d])-([^d])/, '\1 \2') # will mutilate hyphenated-words but shouldn't matter for date extraction
|
53
|
+
string.gsub!(/a half/, 'haAlf') # take the 'a' out so it doesn't turn into a 1, save the half for the end
|
54
|
+
|
55
|
+
# easy/direct replacements
|
56
|
+
|
57
|
+
DIRECT_NUMS.each do |dn|
|
58
|
+
string.gsub!(/#{dn[0]}/i, dn[1])
|
59
|
+
end
|
60
|
+
|
61
|
+
# ten, twenty, etc.
|
62
|
+
|
63
|
+
TEN_PREFIXES.each do |tp|
|
64
|
+
string.gsub!(/(?:#{tp[0]})( *\d(?=[^\d]|$))*/i) { (tp[1] + $1.to_i).to_s }
|
65
|
+
end
|
66
|
+
|
67
|
+
# hundreds, thousands, millions, etc.
|
68
|
+
|
69
|
+
BIG_PREFIXES.each do |bp|
|
70
|
+
string.gsub!(/(\d*) *#{bp[0]}/i) { (bp[1] * $1.to_i).to_s}
|
71
|
+
andition(string)
|
72
|
+
#combine_numbers(string) # Should to be more efficient way to do this
|
73
|
+
end
|
74
|
+
|
75
|
+
# fractional addition
|
76
|
+
# I'm not combining this with the previous block as using float addition complicates the strings
|
77
|
+
# (with extraneous .0's and such )
|
78
|
+
string.gsub!(/(\d+)(?: | and |-)*haAlf/i) { ($1.to_f + 0.5).to_s }
|
79
|
+
|
80
|
+
string
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
def andition(string)
|
85
|
+
sc = StringScanner.new(string)
|
86
|
+
while(sc.scan_until(/(\d+)( | and )(\d+)(?=[^\w]|$)/i))
|
87
|
+
if sc[2] =~ /and/ || sc[1].size > sc[3].size
|
88
|
+
string[(sc.pos - sc.matched_size)..(sc.pos-1)] = (sc[1].to_i + sc[3].to_i).to_s
|
89
|
+
sc.reset
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# def combine_numbers(string)
|
95
|
+
# sc = StringScanner.new(string)
|
96
|
+
# while(sc.scan_until(/(\d+)(?: | and |-)(\d+)(?=[^\w]|$)/i))
|
97
|
+
# string[(sc.pos - sc.matched_size)..(sc.pos-1)] = (sc[1].to_i + sc[2].to_i).to_s
|
98
|
+
# sc.reset
|
99
|
+
# end
|
100
|
+
# end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
module Tickle #:nodoc:
|
2
|
+
class << self #:nodoc:
|
3
|
+
|
4
|
+
# The heavy lifting. Goes through each token groupings to determine what natural language should either by
|
5
|
+
# parsed by Chronic or returned. This methodology makes extension fairly simple, as new token types can be
|
6
|
+
# easily added in repeater and then processed by the guess method
|
7
|
+
#
|
8
|
+
def guess()
|
9
|
+
return nil if @tokens.empty?
|
10
|
+
|
11
|
+
guess_unit_types
|
12
|
+
guess_weekday unless @next
|
13
|
+
guess_month_names unless @next
|
14
|
+
guess_number_and_unit unless @next
|
15
|
+
guess_ordinal unless @next
|
16
|
+
guess_ordinal_and_unit unless @next
|
17
|
+
guess_special unless @next
|
18
|
+
|
19
|
+
# check to see if next is less than now and, if so, set it to next year
|
20
|
+
@next = Time.local(@next.year + 1, @next.month, @next.day, @next.hour, @next.min, @next.sec) if @next && @next.to_date < @start.to_date
|
21
|
+
|
22
|
+
# return the next occurrence
|
23
|
+
return @next.to_time if @next
|
24
|
+
end
|
25
|
+
|
26
|
+
def guess_unit_types
|
27
|
+
@next = @start.bump(:day) if token_types.same?([:day])
|
28
|
+
@next = @start.bump(:week) if token_types.same?([:week])
|
29
|
+
@next = @start.bump(:month) if token_types.same?([:month])
|
30
|
+
@next = @start.bump(:year) if token_types.same?([:year])
|
31
|
+
end
|
32
|
+
|
33
|
+
def guess_weekday
|
34
|
+
@next = chronic_parse_with_start("#{token_of_type(:weekday).start.to_s}") if token_types.same?([:weekday])
|
35
|
+
end
|
36
|
+
|
37
|
+
def guess_month_names
|
38
|
+
@next = chronic_parse_with_start("#{Date::MONTHNAMES[token_of_type(:month_name).start]} 1") if token_types.same?([:month_name])
|
39
|
+
end
|
40
|
+
|
41
|
+
def guess_number_and_unit
|
42
|
+
@next = @start.bump(:day, token_of_type(:number).interval) if token_types.same?([:number, :day])
|
43
|
+
@next = @start.bump(:week, token_of_type(:number).interval) if token_types.same?([:number, :week])
|
44
|
+
@next = @start.bump(:month, token_of_type(:number).interval) if token_types.same?([:number, :month])
|
45
|
+
@next = @start.bump(:year, token_of_type(:number).interval) if token_types.same?([:number, :year])
|
46
|
+
@next = chronic_parse_with_start("#{token_of_type(:month_name).word} #{token_of_type(:number).start}") if token_types.same?([:number, :month_name])
|
47
|
+
@next = chronic_parse_with_start("#{token_of_type(:specific_year).word}-#{token_of_type(:month_name).start}-#{token_of_type(:number).start}") if token_types.same?([:number, :month_name, :specific_year])
|
48
|
+
end
|
49
|
+
|
50
|
+
def guess_ordinal
|
51
|
+
@next = handle_same_day_chronic_issue(@start.year, @start.month, token_of_type(:ordinal).start) if token_types.same?([:ordinal])
|
52
|
+
end
|
53
|
+
|
54
|
+
def guess_ordinal_and_unit
|
55
|
+
@next = handle_same_day_chronic_issue(@start.year, token_of_type(:month_name).start, token_of_type(:ordinal).start) if token_types.same?([:ordinal, :month_name])
|
56
|
+
@next = handle_same_day_chronic_issue(@start.year, @start.month, token_of_type(:ordinal).start) if token_types.same?([:ordinal, :month])
|
57
|
+
@next = handle_same_day_chronic_issue(token_of_type(:specific_year).word, token_of_type(:month_name).start, token_of_type(:ordinal).start) if token_types.same?([:ordinal, :month_name, :specific_year])
|
58
|
+
|
59
|
+
if token_types.same?([:ordinal, :weekday, :month_name])
|
60
|
+
@next = chronic_parse_with_start("#{token_of_type(:ordinal).word} #{token_of_type(:weekday).start.to_s} in #{Date::MONTHNAMES[token_of_type(:month_name).start]}")
|
61
|
+
@next = handle_same_day_chronic_issue(@start.year, token_of_type(:month_name).start, token_of_type(:ordinal).start) if @next.to_date == @start.to_date
|
62
|
+
end
|
63
|
+
|
64
|
+
if token_types.same?([:ordinal, :weekday, :month])
|
65
|
+
@next = chronic_parse_with_start("#{token_of_type(:ordinal).word} #{token_of_type(:weekday).start.to_s} in #{Date::MONTHNAMES[get_next_month(token_of_type(:ordinal).start)]}")
|
66
|
+
@next = handle_same_day_chronic_issue(@start.year, @start.month, token_of_type(:ordinal).start) if @next.to_date == @start.to_date
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def guess_special
|
71
|
+
guess_special_other
|
72
|
+
guess_special_beginning unless @next
|
73
|
+
guess_special_middle unless @next
|
74
|
+
guess_special_end unless @next
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def guess_special_other
|
80
|
+
@next = @start.bump(:day, 2) if token_types.same?([:special, :day]) && token_of_type(:special).start == :other
|
81
|
+
@next = @start.bump(:week, 2) if token_types.same?([:special, :week]) && token_of_type(:special).start == :other
|
82
|
+
@next = chronic_parse_with_start('2 months from now') if token_types.same?([:special, :month]) && token_of_type(:special).start == :other
|
83
|
+
@next = chronic_parse_with_start('2 years from now') if token_types.same?([:special, :year]) && token_of_type(:special).start == :other
|
84
|
+
end
|
85
|
+
|
86
|
+
def guess_special_beginning
|
87
|
+
if token_types.same?([:special, :week]) && token_of_type(:special).start == :beginning then @next = chronic_parse_with_start('Sunday'); end
|
88
|
+
if token_types.same?([:special, :month]) && token_of_type(:special).start == :beginning then @next = Date.civil(@start.year, @start.month + 1, 1); end
|
89
|
+
if token_types.same?([:special, :year]) && token_of_type(:special).start == :beginning then @next = Date.civil(@start.year+1, 1, 1); end
|
90
|
+
end
|
91
|
+
|
92
|
+
def guess_special_end
|
93
|
+
if token_types.same?([:special, :week]) && token_of_type(:special).start == :end then @next = chronic_parse_with_start('Saturday'); end
|
94
|
+
if token_types.same?([:special, :month]) && token_of_type(:special).start == :end then @next = Date.civil(@start.year, @start.month, -1); end
|
95
|
+
if token_types.same?([:special, :year]) && token_of_type(:special).start == :end then @next = Date.new(@start.year, 12, 31); end
|
96
|
+
end
|
97
|
+
|
98
|
+
def guess_special_middle
|
99
|
+
if token_types.same?([:special, :week]) && token_of_type(:special).start == :middle then @next = chronic_parse_with_start('Wednesday'); end
|
100
|
+
if token_types.same?([:special, :month]) && token_of_type(:special).start == :middle then
|
101
|
+
@next = (@start.day > 15 ? Date.civil(@start.year, @start.month + 1, 15) : Date.civil(@start.year, @start.month, 15))
|
102
|
+
end
|
103
|
+
if token_types.same?([:special, :year]) && token_of_type(:special).start == :middle then
|
104
|
+
@next = (@start.day > 15 && @start.month > 6 ? Date.new(@start.year+1, 6, 15) : Date.new(@start.year, 6, 15))
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def token_of_type(type)
|
109
|
+
@tokens.detect {|token| token.type == type}
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# runs Chronic.parse with now being set to the specified start date for Tickle parsing
|
115
|
+
def chronic_parse_with_start(exp)
|
116
|
+
Tickle.dwrite("date expression: #{exp}, start: #{@start}")
|
117
|
+
Chronic.parse(exp, :now => @start)
|
118
|
+
end
|
119
|
+
|
120
|
+
# needed to handle the unique situation where a number or ordinal plus optional month or month name is passed that is EQUAL to the start date since Chronic returns that day.
|
121
|
+
def handle_same_day_chronic_issue(year, month, day)
|
122
|
+
Tickle.dwrite("year (#{year}), month (#{month}), day (#{day})")
|
123
|
+
arg_date = (Date.new(year.to_i, month.to_i, day.to_i) == @start.to_date) ? (Date.new(year.to_i, month.to_i, day.to_i) >> 1).to_time : Time.local(year, month, day)
|
124
|
+
return arg_date
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|