nickel 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/nickel/ztime.rb CHANGED
@@ -1,15 +1,15 @@
1
- # Ruby Nickel Library
2
- # Copyright (c) 2008-2011 Lou Zell, lzell11@gmail.com, http://hazelmade.com
3
- # MIT License [http://www.opensource.org/licenses/mit-license.php]
1
+ require 'time'
4
2
 
5
3
  module Nickel
6
-
4
+
7
5
  class ZTime
8
- # @firm will be used to indicate user provided am/pm
6
+ include Comparable
7
+
8
+ # \@firm will be used to indicate user provided am/pm
9
9
  attr_accessor :firm
10
10
 
11
- # @time is always stored on 24 hour clock, but we could initialize a Time object with ZTime.new("1020", :pm)
12
- # we will convert this to 24 hour clock and set @firm = true
11
+ # \@time is always stored on 24 hour clock, but we could initialize a Time object with ZTime.new("1020", :pm)
12
+ # we will convert this to 24 hour clock and set \@firm = true
13
13
  def initialize(hhmmss = nil, am_pm = nil)
14
14
  t = hhmmss ? hhmmss : ::Time.new.strftime("%H%M%S")
15
15
  t.gsub!(/:/,'') # remove any hyphens, so a user can initialize with something like "2008-10-23"
@@ -20,7 +20,7 @@ module Nickel
20
20
  def time
21
21
  @time
22
22
  end
23
-
23
+
24
24
  def time=(hhmmss)
25
25
  @time = lazy(hhmmss)
26
26
  @firm = false
@@ -30,44 +30,68 @@ module Nickel
30
30
  def hour_str
31
31
  @time[0..1]
32
32
  end
33
-
33
+
34
+ # @deprecated Please use {#min_str} instead
34
35
  def minute_str
36
+ warn "[DEPRECATION] `minute_str` is deprecated. Please use `min_str` instead."
37
+ min_str
38
+ end
39
+
40
+ def min_str
35
41
  @time[2..3]
36
42
  end
37
-
43
+
44
+ # @deprecated Please use {#sec_str} instead
38
45
  def second_str
46
+ warn "[DEPRECATION] `second_str` is deprecated. Please use `sec_str` instead."
47
+ sec_str
48
+ end
49
+
50
+ def sec_str
39
51
  @time[4..5]
40
52
  end
41
-
53
+
42
54
  def hour
43
55
  hour_str.to_i
44
56
  end
45
-
57
+
58
+ # @deprecated Please use {#min} instead
46
59
  def minute
47
- minute_str.to_i
60
+ warn "[DEPRECATION] `minute` is deprecated. Please use `min` instead."
61
+ min
48
62
  end
49
-
63
+
64
+ def min
65
+ min_str.to_i
66
+ end
67
+
68
+ # @deprecated Please use {#sec} instead
50
69
  def second
51
- second_str.to_i
70
+ warn "[DEPRECATION] `second` is deprecated. Please use `sec` instead."
71
+ sec
72
+ end
73
+
74
+ def sec
75
+ sec_str.to_i
52
76
  end
53
77
 
54
- # add_ methods return new ZTime object
55
- # add_ methods take an optional block, the block will be passed the number of days that have passed;
78
+ # add\_ methods return new ZTime object
79
+ # add\_ methods take an optional block, the block will be passed the number of days that have passed;
56
80
  # i.e. adding 48 hours will pass a 2 to the block, this is handy for something like this:
57
81
  # time.add_hours(15) {|x| date.add_days(x)}
58
82
  def add_minutes(number, &block)
59
83
  # new minute is going to be (current minute + number) % 60
60
84
  # number of hours to add is (current minute + number) / 60
61
- hours_to_add = (self.minute + number) / 60
85
+ hours_to_add = (self.min + number) / 60
62
86
  # note add_hours returns a new time object
63
87
  if block_given?
64
88
  o = self.add_hours(hours_to_add, &block)
65
89
  else
66
90
  o = self.add_hours(hours_to_add)
67
91
  end
68
- o.change_minute_to((o.minute + number) % 60) # modifies self
92
+ o.change_minute_to((o.min + number) % 60) # modifies self
69
93
  end
70
-
94
+
71
95
  def add_hours(number, &block)
72
96
  o = self.dup
73
97
  if block_given?
@@ -79,73 +103,73 @@ module Nickel
79
103
 
80
104
  # NOTE: change_ methods modify self.
81
105
  def change_hour_to(h)
82
- self.time = h.to_s2 + minute_str + second_str
106
+ self.time = ZTime.format_time(h, min_str, sec_str)
83
107
  self
84
108
  end
85
-
109
+
86
110
  def change_minute_to(m)
87
- self.time = hour_str + m.to_s2 + second_str
111
+ self.time = ZTime.format_time(hour_str, m, sec_str)
88
112
  self
89
113
  end
90
-
114
+
91
115
  def change_second_to(s)
92
- self.time = hour_str + minute_str + s.to_s2
116
+ self.time = ZTime.format_time(hour_str, min_str, s)
93
117
  self
94
118
  end
95
119
 
96
120
  def readable
97
121
  @time[0..1] + ":" + @time[2..3] + ":" + @time[4..5]
98
122
  end
99
-
123
+
100
124
  def readable_12hr
101
- hour_on_12hr_clock.to_s2 + ":" + @time[2..3] + " #{am_pm}"
125
+ hour_on_12hr_clock + ":" + @time[2..3] + " #{am_pm}"
102
126
  end
103
-
127
+
104
128
  def hour_on_12hr_clock
105
- h = hour % 12
129
+ h = hour % 12
106
130
  h += 12 if h == 0
107
131
  h
108
132
  end
109
-
133
+
110
134
  def is_am?
111
135
  hour < 12 # 0 through 11 on 24hr clock
112
136
  end
113
-
137
+
114
138
  def am_pm
115
139
  is_am? ? "am" : "pm"
116
140
  end
117
-
118
141
 
119
- def <(t2)
120
- (self.hour < t2.hour) || (self.hour == t2.hour && (self.minute < t2.minute || (self.minute == t2.minute && self.second < t2.second)))
121
- end
122
-
123
- def <=(t2)
124
- (self.hour < t2.hour) || (self.hour == t2.hour && (self.minute < t2.minute || (self.minute == t2.minute && self.second <= t2.second)))
125
- end
126
-
127
- def >(t2)
128
- (self.hour > t2.hour) || (self.hour == t2.hour && (self.minute > t2.minute || (self.minute == t2.minute && self.second > t2.second)))
129
- end
130
-
131
- def >=(t2)
132
- (self.hour > t2.hour) || (self.hour == t2.hour && (self.minute > t2.minute || (self.minute == t2.minute && self.second >= t2.second)))
142
+
143
+ def before(t2)
144
+ (t2.respond_to? :hour) && (hour < t2.hour) ||
145
+ (t2.respond_to? :min) && (hour == t2.hour && (min < t2.min ||
146
+ (t2.respond_to? :sec) && (min == t2.min && sec < t2.sec)))
133
147
  end
134
-
135
- def ==(t2)
136
- self.hour == t2.hour && self.minute == t2.minute && self.second == t2.second
148
+
149
+ def after(t2)
150
+ (t2.respond_to? :hour) && (hour > t2.hour) ||
151
+ (t2.respond_to? :min) && (hour == t2.hour && (min > t2.min ||
152
+ (t2.respond_to? :sec) && (min == t2.min && sec > t2.sec)))
137
153
  end
138
-
154
+
139
155
  def <=>(t2)
140
- if self < t2
156
+ if before(t2)
141
157
  -1
142
- elsif self > t2
158
+ elsif after(t2)
143
159
  1
144
160
  else
145
161
  0
146
162
  end
147
163
  end
148
-
164
+
165
+ def to_s
166
+ time
167
+ end
168
+
169
+ def to_time
170
+ Time.parse("#{hour}:#{min}:#{sec}")
171
+ end
172
+
149
173
  class << self
150
174
 
151
175
  # send an array of ZTime objects, this will make a guess at whether they should be am/pm if the user did not specify
@@ -154,7 +178,7 @@ module Nickel
154
178
  # find firm time indices
155
179
  firm_time_indices = []
156
180
  time_array.each_with_index {|t,i| firm_time_indices << i if t.firm}
157
-
181
+
158
182
  if firm_time_indices.empty?
159
183
  # pure guess
160
184
  # DO WE REALLY WANT TO DO THIS?
@@ -170,7 +194,7 @@ module Nickel
170
194
  (min_boundary...max_boundary).to_a.reverse.each do |i| # this says, iterate backwards starting from max_boundary, but not including it, until the min boundary
171
195
  time_array[i].modify_such_that_is_before(time_array[i+1])
172
196
  end
173
-
197
+
174
198
  firm_time_indices.each_index do |j|
175
199
  # now handle all times after first firm time until the next firm time
176
200
  min_boundary = firm_time_indices[j]
@@ -186,10 +210,66 @@ module Nickel
186
210
  # note 12am is 00
187
211
  h % 12
188
212
  end
189
-
213
+
190
214
  def pm_to_24hr(h)
191
215
  h == 12 ? 12 : h + 12
192
216
  end
217
+
218
+ def format_hour(h)
219
+ h.to_s.rjust(2, '0')
220
+ end
221
+
222
+ def format_minute(m)
223
+ m.to_s.rjust(2, '0')
224
+ end
225
+
226
+ def format_second(s)
227
+ s.to_s.rjust(2, '0')
228
+ end
229
+
230
+ # formats the hours, minutes and seconds into the format expected by the ZTime constructor
231
+ def format_time(hours, minutes=0, seconds=0)
232
+ format_hour(hours) + format_minute(minutes) + format_second(seconds)
233
+ end
234
+
235
+ # Interpret Time is an important one, set some goals:
236
+ # match all of the following
237
+ # a.) 5, 12, 530, 1230, 2000
238
+ # b.) 5pm, 12pm, 530am, 1230am,
239
+ # c.) 5:30, 12:30, 20:00
240
+ # d.) 5:3, 12:3, 20:3 ... that's not needed but we supported it in version 1, this would be 5:30 and 12:30
241
+ # e.) 5:30am, 12:30am
242
+ # 20:00am, 20:00pm ... ZTime will flag these as invalid, so it is ok if we match them here
243
+ def interpret(str)
244
+ a_b = /^(\d{1,4})(am|pm)?$/ # handles cases (a) and (b)
245
+ c_d_e = /^(\d{1,2}):(\d{1,2})(am|pm)?$/ # handles cases (c), (d), and (e)
246
+ if mdata = str.match(a_b)
247
+ am_pm = mdata[2]
248
+ # this may look a bit confusing, but all we are doing is interpreting
249
+ # what the user meant based on the number of digits they provided
250
+ if mdata[1].length <= 2
251
+ # e.g. "11" means 11:00
252
+ hstr = mdata[1]
253
+ mstr = "0"
254
+ elsif mdata[1].length == 3
255
+ # e.g. "530" means 5:30
256
+ hstr = mdata[1][0..0]
257
+ mstr = mdata[1][1..2]
258
+ elsif mdata[1].length == 4
259
+ # e.g. "1215" means 12:15
260
+ hstr = mdata[1][0..1]
261
+ mstr = mdata[1][2..3]
262
+ end
263
+ elsif mdata = str.match(c_d_e)
264
+ am_pm = mdata[3]
265
+ hstr = mdata[1]
266
+ mstr = mdata[2]
267
+ else
268
+ return nil
269
+ end
270
+ # in this case we do not care if time fails validation, if it does, it just means we haven't found a valid time, return nil
271
+ begin ZTime.new(ZTime.format_time(hstr, mstr), am_pm) rescue return nil end
272
+ end
193
273
  end
194
274
 
195
275
  # this can very easily be cleaned up
@@ -198,7 +278,7 @@ module Nickel
198
278
  raise "ZTime#modify_such_that_is_before says: time2 does not have @firm set" if !time2.firm
199
279
  # self cannot have @firm set, so all hours will be between 1 and 12
200
280
  # time2 is an end time, self could be its current setting, or off by 12 hours
201
-
281
+
202
282
  # self to time2 --> self to time2
203
283
  # 12 to 2am --> 1200 to 0200
204
284
  # 12 to 12am --> 1200 to 0000
@@ -211,7 +291,7 @@ module Nickel
211
291
  self.hour == 12 ? change_hour_to(0) : change_hour_to(self.hour + 12)
212
292
  end
213
293
  elsif self < time2
214
- if time2.hour >= 12 && ZTime.new((time2.hour - 12).to_s2 + time2.minute_str + time2.second_str) > self
294
+ if time2.hour >= 12 && ZTime.new(ZTime.format_time(time2.hour - 12, time2.min_str, time2.sec_str)) > self
215
295
  # 4 to 5pm or 0400 to 1700
216
296
  change_hour_to(self.hour + 12)
217
297
  else
@@ -225,7 +305,7 @@ module Nickel
225
305
  self.firm = true
226
306
  self
227
307
  end
228
-
308
+
229
309
  def modify_such_that_is_after(time1)
230
310
  raise "ZTime#modify_such_that_is_after says: trying to modify time that has @firm set" if @firm
231
311
  raise "ZTime#modify_such_that_is_after says: time1 does not have @firm set" if !time1.firm
@@ -237,14 +317,14 @@ module Nickel
237
317
  # 930am to 5 ---> 0930 to 0500
238
318
  # 930pm to 5 ---> 2130 to 0500
239
319
  if self < time1
240
- unless time1.hour >= 12 && ZTime.new((time1.hour - 12).to_s2 + time1.minute_str + time1.second_str) >= self
320
+ unless time1.hour >= 12 && ZTime.new(ZTime.format_time(time1.hour - 12, time1.min_str, time1.sec_str)) >= self
241
321
  self.hour == 12 ? change_hour_to(0) : change_hour_to(self.hour + 12)
242
322
  end
243
323
  elsif self > time1
244
324
  # # time1 to self --> time1 to self
245
325
  # # 10am to 11 --> 1000 to 1100
246
- # #
247
- # if time1.hour >= 12 && ZTime.new((time1.hour - 12).to_s2 + time1.minute_str + time1.second_str) > self
326
+ # #
327
+ # if time1.hour >= 12 && ZTime.new(ZTime.format_time(time1.hour - 12, time1.min_str, time1.sec_str)) > self
248
328
  # change_hour_to(self.hour + 12)
249
329
  # else
250
330
  # # do nothing
@@ -269,9 +349,9 @@ module Nickel
269
349
  self.hour == 12 ? change_hour_to(0) : change_hour_to(self.hour + 12)
270
350
  end
271
351
  end
272
-
352
+
273
353
  private
274
-
354
+
275
355
  def adjust_for(am_pm)
276
356
  # how does validation work? Well, we already know that @time is valid, and once we modify we call time= which will
277
357
  # perform validation on the new time. That won't catch something like this though: ZTime.new("2215", :am)
@@ -287,27 +367,27 @@ module Nickel
287
367
  end
288
368
  @firm = true
289
369
  end
290
-
370
+
291
371
  def validate
292
372
  raise "ZTime#validate says: invalid time" unless valid
293
373
  end
294
-
374
+
295
375
  def valid
296
376
  @time.length == 6 && @time !~ /\D/ && valid_hour && valid_minute && valid_second
297
377
  end
298
-
378
+
299
379
  def valid_hour
300
380
  hour >= 0 and hour < 24
301
381
  end
302
-
382
+
303
383
  def valid_minute
304
- minute >= 0 and minute < 60
384
+ min >= 0 and min < 60
305
385
  end
306
-
386
+
307
387
  def valid_second
308
- second >= 0 and second < 60
388
+ sec >= 0 and sec < 60
309
389
  end
310
-
390
+
311
391
  def lazy(s)
312
392
  # someone isn't following directions, but we will let it slide
313
393
  s.length == 1 && s = "0#{s}0000" # only provided h
data/nickel.gemspec CHANGED
@@ -1,40 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'nickel/version'
5
+
1
6
  Gem::Specification.new do |s|
2
- s.name = "nickel"
3
- s.version = "0.0.6"
4
- s.summary = "Natural language date, time, and message parsing."
5
- s.email = "lzell11@gmail.com"
6
- s.homepage = "http://github.com/lzell/nickel"
7
- s.description = "Extracts date, time, and message information from naturally worded text."
8
- s.has_rdoc = true
9
- s.authors = ["Lou Zell"]
10
- s.files =
11
- [
12
- "History.txt",
13
- "License.txt",
14
- "README.rdoc",
15
- "Rakefile",
16
- "nickel.gemspec",
17
- "lib/nickel.rb",
18
- "lib/nickel/construct.rb",
19
- "lib/nickel/construct_finder.rb",
20
- "lib/nickel/construct_interpreter.rb",
21
- "lib/nickel/instance_from_hash.rb",
22
- "lib/nickel/nlp.rb",
23
- "lib/nickel/occurrence.rb",
24
- "lib/nickel/query.rb",
25
- "lib/nickel/query_constants.rb",
26
- "lib/nickel/zdate.rb",
27
- "lib/nickel/ztime.rb",
28
- "lib/nickel/ruby_ext/calling_method.rb",
29
- "lib/nickel/ruby_ext/to_s2.rb",
30
- "test/compare.rb",
31
- "test/nlp_test.rb",
32
- "test/nlp_tests_helper.rb",
33
- "test/zdate_test.rb",
34
- "test/ztime_test.rb",
35
- "spec/nickel_spec.rb"
36
- ]
37
- s.require_paths = ["lib"]
38
- s.rdoc_options = ["--main", "README.rdoc", "--title", "Nickel"]
39
- s.extra_rdoc_files = ["README.rdoc"]
7
+ s.name = "nickel"
8
+ s.version = Nickel::VERSION
9
+ s.summary = "Natural language date, time, and message parsing."
10
+ s.homepage = "http://github.com/iainbeeston/nickel"
11
+ s.description = "Extracts date, time, and message information from naturally worded text."
12
+ s.has_rdoc = true
13
+ s.license = "MIT"
14
+ s.authors = ["Lou Zell", "Iain Beeston"]
15
+
16
+ s.files = `git ls-files`.split($/)
17
+ s.test_files = s.files.grep(%r{^(test|spec)/})
18
+ s.require_paths = ["lib"]
19
+
20
+ if RUBY_ENGINE == 'rbx'
21
+ s.add_dependency 'rubysl-date'
22
+ s.add_dependency 'rubysl-time'
23
+ s.add_development_dependency 'rubysl-rake'
24
+ s.add_development_dependency 'rubysl-bundler'
25
+ end
26
+
27
+ s.add_development_dependency "bundler"
28
+ s.add_development_dependency "rake"
29
+ s.add_development_dependency "rspec", "3.0.0.beta2"
30
+ s.add_development_dependency "coveralls"
31
+ s.add_development_dependency "yard"
32
+ s.add_development_dependency "kramdown"
40
33
  end