nickel 0.0.6 → 0.1.0

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