timerizer 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/timerizer.rb +360 -54
- metadata +1 -1
data/lib/timerizer.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'date'
|
2
2
|
|
3
|
-
# Represents a relative amount of time. For example, `5 days
|
3
|
+
# Represents a relative amount of time. For example, '`5 days`', '`4 years`', and '`5 years, 4 hours, 3 minutes, 2 seconds`' are all RelativeTimes.
|
4
4
|
class RelativeTime
|
5
|
-
# All potential units. Key is the unit name, and the value is its plural form.
|
6
5
|
@@units = {
|
7
6
|
:second => :seconds,
|
8
7
|
:minute => :minutes,
|
@@ -16,7 +15,6 @@ class RelativeTime
|
|
16
15
|
:millennium => :millennia
|
17
16
|
}
|
18
17
|
|
19
|
-
# Unit values in seconds. If a unit is not present in this hash, it is assumed to be in the {@@in_months} hash.
|
20
18
|
@@in_seconds = {
|
21
19
|
:second => 1,
|
22
20
|
:minute => 60,
|
@@ -25,7 +23,6 @@ class RelativeTime
|
|
25
23
|
:week => 604800
|
26
24
|
}
|
27
25
|
|
28
|
-
# Unit values in months. If a unit is not present in this hash, it is assumed to be in the {@@in_seconds} hash.
|
29
26
|
@@in_months = {
|
30
27
|
:month => 1,
|
31
28
|
:year => 12,
|
@@ -40,6 +37,69 @@ class RelativeTime
|
|
40
37
|
:year => 31556952
|
41
38
|
}
|
42
39
|
|
40
|
+
# Default syntax formats that can be used with #to_s
|
41
|
+
# @see #to_s
|
42
|
+
@@syntaxes = {
|
43
|
+
:micro => {
|
44
|
+
:units => {
|
45
|
+
:seconds => 's',
|
46
|
+
:minutes => 'm',
|
47
|
+
:hours => 'h',
|
48
|
+
:days => 'd',
|
49
|
+
:weeks => 'w',
|
50
|
+
:months => 'mn',
|
51
|
+
:years => 'y',
|
52
|
+
},
|
53
|
+
:separator => '',
|
54
|
+
:delimiter => ' ',
|
55
|
+
:count => 1
|
56
|
+
},
|
57
|
+
:short => {
|
58
|
+
:units => {
|
59
|
+
:seconds => 'sec',
|
60
|
+
:minutes => 'min',
|
61
|
+
:hours => 'hr',
|
62
|
+
:days => 'd',
|
63
|
+
:weeks => 'wk',
|
64
|
+
:months => 'mn',
|
65
|
+
:years => 'yr',
|
66
|
+
:centuries => 'ct',
|
67
|
+
:millenia => 'ml'
|
68
|
+
},
|
69
|
+
:separator => '',
|
70
|
+
:delimiter => ' ',
|
71
|
+
:count => 2
|
72
|
+
},
|
73
|
+
:long => {
|
74
|
+
:units => {
|
75
|
+
:seconds => ['second', 'seconds'],
|
76
|
+
:minutes => ['minute', 'minutes'],
|
77
|
+
:hours => ['hour', 'hours'],
|
78
|
+
:days => ['day', 'days'],
|
79
|
+
:weeks => ['week', 'weeks'],
|
80
|
+
:months => ['month', 'months'],
|
81
|
+
:years => ['year', 'years'],
|
82
|
+
:centuries => ['century', 'centuries'],
|
83
|
+
:millennia => ['millenium', 'millenia'],
|
84
|
+
}
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
# All potential units. Key is the unit name, and the value is its plural form.
|
89
|
+
def self.units
|
90
|
+
@@units
|
91
|
+
end
|
92
|
+
|
93
|
+
# Unit values in seconds. If a unit is not present in this hash, it is assumed to be in the {@@in_months} hash.
|
94
|
+
def self.units_in_seconds
|
95
|
+
@@in_seconds
|
96
|
+
end
|
97
|
+
|
98
|
+
# Unit values in months. If a unit is not present in this hash, it is assumed to be in the {@@in_seconds} hash.
|
99
|
+
def self.units_in_months
|
100
|
+
@@in_months
|
101
|
+
end
|
102
|
+
|
43
103
|
# Initialize a new instance of RelativeTime.
|
44
104
|
# @overload new(hash)
|
45
105
|
# @param [Hash] units The base units to initialize with
|
@@ -47,21 +107,20 @@ class RelativeTime
|
|
47
107
|
# @option units [Fixnum] :months The number of months
|
48
108
|
# @overload new(count, unit)
|
49
109
|
# @param [Fixnum] count The number of units to initialize with
|
50
|
-
# @param [Symbol] unit The unit to initialize. See {
|
110
|
+
# @param [Symbol] unit The unit to initialize. See {RelativeTime#units}
|
51
111
|
def initialize(count = 0, unit = :second)
|
52
|
-
if
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
@seconds = 0
|
59
|
-
@months = 0
|
112
|
+
if count.is_a? Hash
|
113
|
+
units = count
|
114
|
+
units.default = 0
|
115
|
+
@seconds, @months = units.values_at(:seconds, :months)
|
116
|
+
else
|
117
|
+
@seconds = @months = 0
|
60
118
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
119
|
+
if @@in_seconds.has_key?(unit)
|
120
|
+
@seconds = count * @@in_seconds.fetch(unit)
|
121
|
+
elsif @@in_months.has_key?(unit)
|
122
|
+
@months = count * @@in_months.fetch(unit)
|
123
|
+
end
|
65
124
|
end
|
66
125
|
end
|
67
126
|
|
@@ -70,8 +129,11 @@ class RelativeTime
|
|
70
129
|
# @return [Boolean] True if both RelativeTimes are equal
|
71
130
|
# @note Be weary of rounding; this method compares both RelativeTimes' base units
|
72
131
|
def ==(time)
|
73
|
-
|
74
|
-
|
132
|
+
if time.is_a?(RelativeTime)
|
133
|
+
@seconds == time.get(:seconds) && @months == time.get(:months)
|
134
|
+
else
|
135
|
+
false
|
136
|
+
end
|
75
137
|
end
|
76
138
|
|
77
139
|
# Return the number of base units in a RelativeTime.
|
@@ -79,16 +141,20 @@ class RelativeTime
|
|
79
141
|
# @return [Fixnum] The requested unit count
|
80
142
|
# @raise [ArgumentError] Unit requested was not :seconds or :months
|
81
143
|
def get(unit)
|
82
|
-
|
83
|
-
|
84
|
-
|
144
|
+
if unit == :seconds
|
145
|
+
@seconds
|
146
|
+
elsif unit == :months
|
147
|
+
@months
|
148
|
+
else
|
149
|
+
raise ArgumentError
|
150
|
+
end
|
85
151
|
end
|
86
152
|
|
87
153
|
# Determines the time between RelativeTime and the given time.
|
88
154
|
# @param [Time] time The initial time.
|
89
155
|
# @return [Time] The difference between the current RelativeTime and the given time
|
90
156
|
# @example 5 hours before January 1st, 2000 at noon
|
91
|
-
# 5.minutes.before(Time.
|
157
|
+
# 5.minutes.before(Time.new(2000, 1, 1, 12, 00, 00))
|
92
158
|
# => 2000-01-01 11:55:00 -0800
|
93
159
|
# @see #ago
|
94
160
|
# @see #after
|
@@ -102,7 +168,7 @@ class RelativeTime
|
|
102
168
|
new_month += 12
|
103
169
|
new_year -= 1
|
104
170
|
end
|
105
|
-
if
|
171
|
+
if Date.valid_date?(new_year, new_month, time.day)
|
106
172
|
new_day = time.day
|
107
173
|
else
|
108
174
|
new_day = Date.new(new_year, new_month).days_in_month
|
@@ -135,7 +201,7 @@ class RelativeTime
|
|
135
201
|
new_year += 1
|
136
202
|
new_month -= 12
|
137
203
|
end
|
138
|
-
if
|
204
|
+
if Date.valid_date?(new_year, new_month, time.day)
|
139
205
|
new_day = time.day
|
140
206
|
else
|
141
207
|
new_day = Date.new(new_year, new_month).days_in_month
|
@@ -161,9 +227,9 @@ class RelativeTime
|
|
161
227
|
superior_unit = @@units.keys.index(unit) + 1
|
162
228
|
|
163
229
|
define_method(in_method) do
|
164
|
-
if
|
230
|
+
if @@in_seconds.has_key?(unit)
|
165
231
|
@seconds / @@in_seconds[unit]
|
166
|
-
elsif
|
232
|
+
elsif @@in_months.has_key?(unit)
|
167
233
|
@months / @@in_months[unit]
|
168
234
|
end
|
169
235
|
end
|
@@ -173,7 +239,7 @@ class RelativeTime
|
|
173
239
|
count_superior = @@units.keys[superior_unit]
|
174
240
|
|
175
241
|
time = self.send(in_method)
|
176
|
-
if
|
242
|
+
if @@units.length > superior_unit
|
177
243
|
time -= self.send(in_superior).send(count_superior).send(in_method)
|
178
244
|
end
|
179
245
|
time
|
@@ -188,14 +254,16 @@ class RelativeTime
|
|
188
254
|
# @see #average!
|
189
255
|
# @see #unaverage
|
190
256
|
def average
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
257
|
+
if @seconds > 0
|
258
|
+
months = (@seconds / @@average_seconds[:month])
|
259
|
+
seconds = @seconds - months.months.unaverage.get(:seconds)
|
260
|
+
RelativeTime.new(
|
261
|
+
:seconds => seconds,
|
262
|
+
:months => months + @months
|
263
|
+
)
|
264
|
+
else
|
265
|
+
self
|
266
|
+
end
|
199
267
|
end
|
200
268
|
|
201
269
|
# Destructively average second-based units to month-based units.
|
@@ -217,7 +285,7 @@ class RelativeTime
|
|
217
285
|
def unaverage
|
218
286
|
seconds = @@average_seconds[:month] * @months
|
219
287
|
seconds += @seconds
|
220
|
-
RelativeTime.new(
|
288
|
+
RelativeTime.new(:seconds => seconds)
|
221
289
|
end
|
222
290
|
|
223
291
|
# Destructively average month-based units to second-based units.
|
@@ -251,32 +319,252 @@ class RelativeTime
|
|
251
319
|
})
|
252
320
|
end
|
253
321
|
|
322
|
+
# Converts {RelativeTime} to {WallClock}
|
323
|
+
# @return [WallClock] {RelativeTime} as {WallClock}
|
324
|
+
# @example
|
325
|
+
# (17.hours 30.minutes).to_wall
|
326
|
+
# # => 5:30:00 PM
|
327
|
+
def to_wall
|
328
|
+
raise WallClock::TimeOutOfBoundsError if @months > 0
|
329
|
+
WallClock.new(:second => @seconds)
|
330
|
+
end
|
331
|
+
|
254
332
|
# Convert {RelativeTime} to a human-readable format.
|
333
|
+
# @overload to_s(syntax)
|
334
|
+
# @param [Symbol] syntax The syntax from @@syntaxes to use
|
335
|
+
# @overload to_s(hash)
|
336
|
+
# @param [Hash] hash The custom hash to use
|
337
|
+
# @option hash [Hash] :units The unit names to use. See @@syntaxes for examples
|
338
|
+
# @option hash [Fixnum] :count The maximum number of units to output. `1` would output only the unit of greatest example (such as the hour value in `1.hour 3.minutes 2.seconds`).
|
339
|
+
# @option hash [String] :separator The separator to use in between a unit and its value
|
340
|
+
# @option hash [String] :delimiter The delimiter to use in between different unit-value pairs
|
255
341
|
# @example
|
256
342
|
# (14.months 49.hours).to_s
|
257
343
|
# => 2 years, 2 months, 3 days, 1 hour
|
258
|
-
|
259
|
-
|
344
|
+
# (1.day 3.hours 4.minutes).to_s(:short)
|
345
|
+
# => 1d 3hr
|
346
|
+
# @raise KeyError Symbol argument isn't in @@syntaxes
|
347
|
+
# @raise ArgumentError Argument isn't a hash (if not a symbol)
|
348
|
+
# @see @@syntaxes
|
349
|
+
def to_s(syntax = :long)
|
350
|
+
if syntax.is_a? Symbol
|
351
|
+
syntax = @@syntaxes.fetch(syntax)
|
352
|
+
end
|
260
353
|
|
261
|
-
|
262
|
-
|
263
|
-
|
354
|
+
raise ArgumentError unless syntax.is_a? Hash
|
355
|
+
times = []
|
356
|
+
|
357
|
+
if syntax[:count].nil? || syntax[:count] == :all
|
358
|
+
syntax[:count] = @@units.count
|
359
|
+
end
|
360
|
+
units = syntax.fetch(:units)
|
361
|
+
|
362
|
+
count = 0
|
363
|
+
units = Hash[units.to_a.reverse]
|
364
|
+
units.each do |unit, (singular, plural)|
|
365
|
+
if count < syntax.fetch(:count)
|
366
|
+
time = self.respond_to?(unit) ? self.send(unit) : 0
|
367
|
+
|
368
|
+
if time > 1 && !plural.nil?
|
369
|
+
times << [time, plural]
|
370
|
+
count += 1
|
371
|
+
elsif time > 0
|
372
|
+
times << [time, singular]
|
373
|
+
count += 1
|
374
|
+
end
|
375
|
+
end
|
264
376
|
end
|
265
377
|
|
266
378
|
times.map do |time|
|
267
|
-
time.join(' ')
|
268
|
-
end.
|
379
|
+
time.join(syntax[:separator] || ' ')
|
380
|
+
end.join(syntax[:delimiter] || ', ')
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
# Represents a time, but not a date. '`7:00 PM`' would be an example of a WallClock object
|
385
|
+
class WallClock
|
386
|
+
# Represents an error where an invalid meridiem was passed to WallClock.
|
387
|
+
# @see #new
|
388
|
+
class InvalidMeridiemError < ArgumentError; end
|
389
|
+
# Represents an error where a time beyond 24 hours was passed to WallClock.
|
390
|
+
# @see #new
|
391
|
+
class TimeOutOfBoundsError < ArgumentError; end
|
392
|
+
|
393
|
+
# Initialize a new instance of WallClock
|
394
|
+
# @overload new(hash)
|
395
|
+
# @param [Hash] units The units to initialize with
|
396
|
+
# @option units [Fixnum] :hour The hour to initialize with
|
397
|
+
# @option units [Fixnum] :minute The minute to initialize with
|
398
|
+
# @option units [Fixnum] :second The second to initialize with
|
399
|
+
# @overload new(hour, minute, meridiem)
|
400
|
+
# @param [Fixnum] hour The hour to initialize with
|
401
|
+
# @param [Fixnum] minute The minute to initialize with
|
402
|
+
# @param [Symbol] meridiem The meridiem to initialize with (`:am` or `:pm`)
|
403
|
+
# @overload new(hour, minute, second, meridiem)
|
404
|
+
# @param [Fixnum] hour The hour to initialize with
|
405
|
+
# @param [Fixnum] minute The minute to initialize with
|
406
|
+
# @param [Fixnum] second The second to initialize with
|
407
|
+
# @param [Symbol] meridiem The meridiem to initialize with (`:am` or `:pm`)
|
408
|
+
# @raise InvalidMeridiemError Meridiem is not `:am` or `:pm`
|
409
|
+
def initialize(hour = 0, minute = 0, second = 0, meridiem = :am)
|
410
|
+
if hour.is_a?(Hash)
|
411
|
+
units = hour
|
412
|
+
|
413
|
+
second = units[:second] || 0
|
414
|
+
minute = units[:minute] || 0
|
415
|
+
hour = units[:hour] || 0
|
416
|
+
else
|
417
|
+
if second.is_a?(String) || second.is_a?(Symbol)
|
418
|
+
meridiem = second
|
419
|
+
second = 0
|
420
|
+
end
|
421
|
+
|
422
|
+
meridiem = meridiem.downcase.to_sym
|
423
|
+
if !(meridiem == :am || meridiem == :pm)
|
424
|
+
raise InvalidMeridiemError
|
425
|
+
elsif meridiem == :pm && hour > 12
|
426
|
+
raise TimeOutOfBoundsError, "hour must be <= 12 for PM"
|
427
|
+
elsif hour >= 24 || minute >= 60 || second >= 60
|
428
|
+
raise TimeOutOfBoundsError
|
429
|
+
end
|
430
|
+
|
431
|
+
hour += 12 if meridiem == :pm
|
432
|
+
end
|
433
|
+
|
434
|
+
@seconds =
|
435
|
+
RelativeTime.units_in_seconds.fetch(:hour) * hour +
|
436
|
+
RelativeTime.units_in_seconds.fetch(:minute) * minute +
|
437
|
+
second
|
438
|
+
|
439
|
+
if @seconds >= RelativeTime.units_in_seconds.fetch(:day)
|
440
|
+
raise TimeOutOfBoundsError
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
# Returns the time of the WallClock on a date
|
445
|
+
# @param [Date] date The date to apply the time on
|
446
|
+
# @return [Time] The time after the given date
|
447
|
+
# @example yesterday at 5:00
|
448
|
+
# time = WallClock.new(5, 00, :pm)
|
449
|
+
# time.on(Date.yesterday)
|
450
|
+
# => 2000-1-1 17:00:00 -0800
|
451
|
+
def on(date)
|
452
|
+
date.to_date.to_time + @seconds
|
453
|
+
end
|
454
|
+
|
455
|
+
# Comparse two {WallClock}s.
|
456
|
+
# @return [Boolean] True if the WallClocks are identical
|
457
|
+
def ==(time)
|
458
|
+
if time.is_a? WallClock
|
459
|
+
self.in_seconds == time.in_seconds
|
460
|
+
else
|
461
|
+
false
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
# Get the time of the WallClock, in seconds
|
466
|
+
# @return [Fixnum] The total time of the WallClock, in seconds
|
467
|
+
def in_seconds
|
468
|
+
@seconds
|
469
|
+
end
|
470
|
+
|
471
|
+
# Get the time of the WallClock, in minutes
|
472
|
+
# @return [Fixnum] The total time of the WallClock, in minutes
|
473
|
+
def in_minutes
|
474
|
+
@seconds / RelativeTime.units_in_seconds[:minute]
|
475
|
+
end
|
476
|
+
|
477
|
+
# Get the time of the WallClock, in hours
|
478
|
+
# @return [Fixnum] The total time of the WallClock, in hours
|
479
|
+
def in_hours
|
480
|
+
@seconds / RelativeTime.units_in_seconds[:hour]
|
481
|
+
end
|
482
|
+
|
483
|
+
# Get the second of the WallClock.
|
484
|
+
# @return [Fixnum] The second component of the WallClock
|
485
|
+
def second
|
486
|
+
self.to_relative.seconds
|
487
|
+
end
|
488
|
+
|
489
|
+
# Get the minute of the WallClock.
|
490
|
+
# @return [Fixnum] The minute component of the WallClock
|
491
|
+
def minute
|
492
|
+
self.to_relative.minutes
|
493
|
+
end
|
494
|
+
|
495
|
+
# Get the hour of the WallClock.
|
496
|
+
# @param [Symbol] system The houring system to use (either `:twelve_hour` or `:twenty_four_hour`; default `:twenty_four_hour`)
|
497
|
+
# @return [Fixnum] The hour component of the WallClock
|
498
|
+
def hour(system = :twenty_four_hour)
|
499
|
+
hour = self.to_relative.hours
|
500
|
+
if (system == :twelve_hour) && hour > 12
|
501
|
+
hour - 12
|
502
|
+
elsif (system == :twenty_four_hour)
|
503
|
+
hour
|
504
|
+
else
|
505
|
+
raise ArgumentError, "system should be :twelve_hour or :twenty_four_hour"
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
# Get the meridiem of the WallClock.
|
510
|
+
# @return [Symbol] The meridiem (either `:am` or `:pm`)
|
511
|
+
def meridiem
|
512
|
+
if self.hour > 12
|
513
|
+
:pm
|
514
|
+
else
|
515
|
+
:am
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
# Converts self to {WallClock}
|
520
|
+
# @see Time#to_wall
|
521
|
+
def to_wall
|
522
|
+
self
|
523
|
+
end
|
524
|
+
|
525
|
+
# Converts {WallClock} to {RelativeTime}
|
526
|
+
# @return [RelativeTime] {WallClock} as {RelativeTime}
|
527
|
+
# @example
|
528
|
+
# time = WallClock.new(5, 30, :pm)
|
529
|
+
# time.to_relative
|
530
|
+
# => 5 hours, 30 minutes
|
531
|
+
def to_relative
|
532
|
+
@seconds.seconds
|
533
|
+
end
|
534
|
+
|
535
|
+
# Convert {WallClock} to a human-readable format.
|
536
|
+
# @param [Symbol] system The hour system to use (`:twelve_hour` or `:twenty_four_hour`; default `:twelve_hour`)
|
537
|
+
# @example
|
538
|
+
# time = WallClock.new(5, 37, :pm)
|
539
|
+
# time.to_s
|
540
|
+
# => "5:37:00 PM"
|
541
|
+
# time.to_s(:twenty_four_hour)
|
542
|
+
# => "17:37:00"
|
543
|
+
# @raise ArgumentError Argument isn't a proper system
|
544
|
+
def to_s(system = :twelve_hour)
|
545
|
+
if(system == :twelve_hour)
|
546
|
+
meridiem = self.meridiem.to_s.upcase
|
547
|
+
"#{self.hour(system)}:#{self.minute}:#{self.second} #{meridiem}"
|
548
|
+
elsif(system == :twenty_four_hour)
|
549
|
+
"#{self.hour(system)}:#{self.minute}:#{self.second}"
|
550
|
+
else
|
551
|
+
raise ArgumentError, "system should be :twelve_hour or :twenty_four_hour"
|
552
|
+
end
|
269
553
|
end
|
270
554
|
end
|
271
555
|
|
272
556
|
# {Time} class monkeywrenched with {RelativeTime} support.
|
273
557
|
class Time
|
274
|
-
|
275
|
-
|
558
|
+
# Represents an error where two times were expected to be in the future, but were in the past.
|
559
|
+
# @see #until
|
560
|
+
class TimeIsInThePastError < ArgumentError; end
|
561
|
+
# Represents an error where two times were expected to be in the past, but were in the future.
|
562
|
+
# @see #since
|
563
|
+
class TimeIsInTheFutureError < ArgumentError; end
|
276
564
|
|
277
565
|
add = instance_method(:+)
|
278
566
|
define_method(:+) do |time|
|
279
|
-
if
|
567
|
+
if time.is_a? RelativeTime
|
280
568
|
time.after(self)
|
281
569
|
else
|
282
570
|
add.bind(self).(time)
|
@@ -285,7 +573,7 @@ class Time
|
|
285
573
|
|
286
574
|
subtract = instance_method(:-)
|
287
575
|
define_method(:-) do |time|
|
288
|
-
if
|
576
|
+
if time.is_a? RelativeTime
|
289
577
|
time.before(self)
|
290
578
|
else
|
291
579
|
subtract.bind(self).(time)
|
@@ -302,13 +590,13 @@ class Time
|
|
302
590
|
# @see Time#since
|
303
591
|
# @see Time#between
|
304
592
|
def self.until(time)
|
305
|
-
raise
|
593
|
+
raise TimeIsInThePastError if Time.now > time.to_time
|
306
594
|
|
307
595
|
Time.between(Time.now, time)
|
308
596
|
end
|
309
597
|
|
310
598
|
# Calculates the time since a given time
|
311
|
-
# @param [Time]
|
599
|
+
# @param [Time] time The time to calculate since now
|
312
600
|
# @return [RelativeTime] The time since the provided time
|
313
601
|
# @raise[TimeIsInTheFutureException] The provided time is in the future
|
314
602
|
# @example
|
@@ -317,7 +605,7 @@ class Time
|
|
317
605
|
# @see Time#since
|
318
606
|
# @see Time#between
|
319
607
|
def self.since(time)
|
320
|
-
raise
|
608
|
+
raise TimeIsInTheFutureError if time.to_time > Time.now
|
321
609
|
|
322
610
|
Time.between(Time.now, time)
|
323
611
|
end
|
@@ -352,6 +640,17 @@ class Time
|
|
352
640
|
def to_time
|
353
641
|
self
|
354
642
|
end
|
643
|
+
|
644
|
+
# Converts {Time} to {WallClock}
|
645
|
+
# @return [WallClock] {Time} as {WallClock}
|
646
|
+
# @example
|
647
|
+
# time = Time.now.to_wall
|
648
|
+
# Date.tomorrow.at(time)
|
649
|
+
# => 2000-1-2 13:13:27 -0800
|
650
|
+
# # "Same time tomorrow?"
|
651
|
+
def to_wall
|
652
|
+
WallClock.new(self.hour, self.min, self.sec)
|
653
|
+
end
|
355
654
|
end
|
356
655
|
|
357
656
|
# {Date} class monkeywrenched with {RelativeTime} helpers.
|
@@ -377,6 +676,14 @@ class Date
|
|
377
676
|
self
|
378
677
|
end
|
379
678
|
|
679
|
+
# Apply a time to a date
|
680
|
+
# @example yesterday at 5:00
|
681
|
+
# Date.yesterday.at(WallClock.new(5, 00, :pm))
|
682
|
+
# => 2000-1-1 17:00:00 -0800
|
683
|
+
def at(time)
|
684
|
+
time.to_wall.on(self)
|
685
|
+
end
|
686
|
+
|
380
687
|
# Return tomorrow as {Date}.
|
381
688
|
# @see Date#yesterday
|
382
689
|
def self.tomorrow
|
@@ -394,10 +701,9 @@ end
|
|
394
701
|
# @example
|
395
702
|
# 5.minutes
|
396
703
|
# => 5 minutes
|
397
|
-
# @see RelativeTime
|
704
|
+
# @see {RelativeTime#units}
|
398
705
|
class Fixnum
|
399
|
-
|
400
|
-
units.each do |unit, plural|
|
706
|
+
RelativeTime.units.each do |unit, plural|
|
401
707
|
define_method(unit) do |added_time = RelativeTime.new|
|
402
708
|
time = RelativeTime.new(self, unit)
|
403
709
|
time + added_time
|