duration 0.0.2 → 0.0.3
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/duration.rb +170 -51
- metadata +2 -2
data/lib/duration.rb
CHANGED
@@ -27,7 +27,10 @@
|
|
27
27
|
# => "2 w, 0 d, 0 h, 2 m, 30 s"
|
28
28
|
#
|
29
29
|
class Duration
|
30
|
-
|
30
|
+
include Comparable
|
31
|
+
include Enumerable
|
32
|
+
|
33
|
+
attr_reader :total, :weeks, :days, :hours, :minutes
|
31
34
|
|
32
35
|
WEEK = 60 * 60 * 24 * 7
|
33
36
|
DAY = 60 * 60 * 24
|
@@ -41,18 +44,23 @@ class Duration
|
|
41
44
|
#
|
42
45
|
# d = Duration.new(60 * 60 * 24 * 10 + 120 + 30)
|
43
46
|
# => #<Duration: 1 week, 3 days, 2 minutes and 30 seconds>
|
44
|
-
#
|
45
47
|
# d = Duration.new(:weeks => 1, :days => 3, :minutes => 2, :seconds => 30)
|
46
48
|
# => #<Duration: 1 week, 3 days, 2 minutes and 30 seconds>
|
47
49
|
#
|
48
|
-
def initialize(seconds_or_attr)
|
49
|
-
if
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
seconds
|
55
|
-
|
50
|
+
def initialize(seconds_or_attr = 0)
|
51
|
+
if seconds_or_attr.kind_of? Hash
|
52
|
+
# Part->time map table.
|
53
|
+
h = {:weeks => WEEK, :days => DAY, :hours => HOUR, :minutes => MINUTE, :seconds => SECOND}
|
54
|
+
|
55
|
+
# Loop through each valid part, ignore all others.
|
56
|
+
seconds = seconds_or_attr.inject(0) do |sec, args|
|
57
|
+
# Grab the part of the duration (week, day, whatever) and the number of seconds for it.
|
58
|
+
part, time = args
|
59
|
+
|
60
|
+
# Map each part to their number of seconds and the given value.
|
61
|
+
# {:weeks => 2} maps to h[:weeks] -- so... weeks = WEEK * 2
|
62
|
+
if h.key?(prt = part.to_s.to_sym) then sec + time * h[prt] else 0 end
|
63
|
+
end
|
56
64
|
else
|
57
65
|
seconds = seconds_or_attr
|
58
66
|
end
|
@@ -69,12 +77,14 @@ class Duration
|
|
69
77
|
#
|
70
78
|
# *Identifiers*
|
71
79
|
#
|
72
|
-
# %w
|
73
|
-
# %d
|
74
|
-
# %h
|
75
|
-
# %m
|
76
|
-
# %s
|
77
|
-
#
|
80
|
+
# %w -- Number of weeks
|
81
|
+
# %d -- Number of days
|
82
|
+
# %h -- Number of hours
|
83
|
+
# %m -- Number of minutes
|
84
|
+
# %s -- Number of seconds
|
85
|
+
# %t -- Total number of seconds
|
86
|
+
# %x -- Duration#to_s
|
87
|
+
# %% -- Literal `%' character
|
78
88
|
#
|
79
89
|
# *Example*
|
80
90
|
#
|
@@ -89,36 +99,146 @@ class Duration
|
|
89
99
|
'd' => @days ,
|
90
100
|
'h' => @hours ,
|
91
101
|
'm' => @minutes,
|
92
|
-
's' => @seconds
|
102
|
+
's' => @seconds,
|
103
|
+
't' => @total ,
|
104
|
+
'x' => to_s}
|
93
105
|
|
94
|
-
fmt.gsub(/%?%(w|d|h|m|s)/) do |match|
|
106
|
+
fmt.gsub(/%?%(w|d|h|m|s|t|x)/) do |match|
|
95
107
|
match.size == 3 ? match : h[match[1..1]]
|
96
108
|
end.gsub('%%', '%')
|
97
109
|
end
|
98
110
|
|
99
|
-
#
|
100
|
-
#
|
111
|
+
# Get the number of seconds of a given part, or simply just get the number of
|
112
|
+
# seconds.
|
101
113
|
#
|
102
114
|
# *Example*
|
103
115
|
#
|
104
|
-
# d = Duration.new(:days =>
|
105
|
-
# => #<Duration:
|
106
|
-
# d.
|
107
|
-
# =>
|
108
|
-
#
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
116
|
+
# d = Duration.new(:weeks => 1, :days => 1, :hours => 1, :seconds => 30)
|
117
|
+
# => #<Duration: 1 week, 1 day, 1 hour and 30 seconds>
|
118
|
+
# d.seconds(:weeks)
|
119
|
+
# => 604800
|
120
|
+
# d.seconds(:days)
|
121
|
+
# => 86400
|
122
|
+
# d.seconds(:hours)
|
123
|
+
# => 3600
|
124
|
+
# d.seconds
|
125
|
+
# => 30
|
126
|
+
#
|
127
|
+
def seconds(part = nil)
|
128
|
+
# Table mapping
|
129
|
+
h = {:weeks => WEEK, :days => DAY, :hours => HOUR, :minutes => MINUTE}
|
130
|
+
|
131
|
+
if [:weeks, :days, :hours, :minutes].include? part
|
132
|
+
__send__(part) * h[part]
|
117
133
|
else
|
118
|
-
|
134
|
+
@seconds
|
119
135
|
end
|
120
136
|
end
|
121
137
|
|
138
|
+
# For iterating through the duration set of weeks, days, hours, minutes, and
|
139
|
+
# seconds.
|
140
|
+
#
|
141
|
+
# *Example*
|
142
|
+
#
|
143
|
+
# Duration.new(:weeks => 1, :seconds => 30).each do |part, time|
|
144
|
+
# puts "part: #{part}, time: #{time}"
|
145
|
+
# end
|
146
|
+
#
|
147
|
+
# _Output_
|
148
|
+
#
|
149
|
+
# part: weeks, time: 1
|
150
|
+
# part: days, time: 0
|
151
|
+
# part: hours, time: 0
|
152
|
+
# part: minutes, time: 0
|
153
|
+
# part: seconds, time: 30
|
154
|
+
#
|
155
|
+
def each
|
156
|
+
[['weeks' , @weeks ],
|
157
|
+
['days' , @days ],
|
158
|
+
['hours' , @hours ],
|
159
|
+
['minutes' , @minutes],
|
160
|
+
['seconds' , @seconds]].each do |part, time|
|
161
|
+
# Yield to block
|
162
|
+
yield part, time
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Calls `<=>' on Duration#total.
|
167
|
+
#
|
168
|
+
# *Example*
|
169
|
+
#
|
170
|
+
# 5.days == 24.hours * 5
|
171
|
+
# => true
|
172
|
+
#
|
173
|
+
def <=>(other)
|
174
|
+
@total <=> other.to_i
|
175
|
+
end
|
176
|
+
|
177
|
+
# Set the number of weeks.
|
178
|
+
#
|
179
|
+
# *Example*
|
180
|
+
#
|
181
|
+
# d = Duration.new(0)
|
182
|
+
# => #<Duration: ...>
|
183
|
+
# d.weeks = 2; d
|
184
|
+
# => #<Duration: 2 weeks>
|
185
|
+
#
|
186
|
+
def weeks=(n)
|
187
|
+
initialize(:weeks => n, :seconds => @total - seconds(:weeks))
|
188
|
+
end
|
189
|
+
|
190
|
+
# Set the number of days.
|
191
|
+
#
|
192
|
+
# *Example*
|
193
|
+
#
|
194
|
+
# d = Duration.new(0)
|
195
|
+
# => #<Duration: ...>
|
196
|
+
# d.days = 5; d
|
197
|
+
# => #<Duration: 5 days>
|
198
|
+
#
|
199
|
+
def days=(n)
|
200
|
+
initialize(:days => n, :seconds => @total - seconds(:days))
|
201
|
+
end
|
202
|
+
|
203
|
+
# Set the number of hours.
|
204
|
+
#
|
205
|
+
# *Example*
|
206
|
+
#
|
207
|
+
# d = Duration.new(0)
|
208
|
+
# => #<Duration: ...>
|
209
|
+
# d.hours = 5; d
|
210
|
+
# => #<Duration: 5 hours>
|
211
|
+
#
|
212
|
+
def hours=(n)
|
213
|
+
initialize(:hours => n, :seconds => @total - seconds(:hours))
|
214
|
+
end
|
215
|
+
|
216
|
+
# Set the number of minutes.
|
217
|
+
#
|
218
|
+
# *Example*
|
219
|
+
#
|
220
|
+
# d = Duration.new(0)
|
221
|
+
# => #<Duration: ...>
|
222
|
+
# d.minutes = 30; d
|
223
|
+
# => #<Duration: 30 minutes>
|
224
|
+
#
|
225
|
+
def minutes=(n)
|
226
|
+
initialize(:minutes => n, :seconds => @total - seconds(:minutes))
|
227
|
+
end
|
228
|
+
|
229
|
+
# Set the number of minutes.
|
230
|
+
#
|
231
|
+
# *Example*
|
232
|
+
#
|
233
|
+
# d = Duration.new(0)
|
234
|
+
# => #<Duration: ...>
|
235
|
+
# d.seconds = 30; d
|
236
|
+
# => #<Duration: 30 seconds>
|
237
|
+
#
|
238
|
+
def seconds=(n)
|
239
|
+
initialize(:seconds => (@total + n) - @seconds)
|
240
|
+
end
|
241
|
+
|
122
242
|
# Friendly, human-readable string representation of the duration.
|
123
243
|
#
|
124
244
|
# *Example*
|
@@ -131,12 +251,7 @@ class Duration
|
|
131
251
|
def to_s
|
132
252
|
str = ''
|
133
253
|
|
134
|
-
|
135
|
-
['days' , @days ],
|
136
|
-
['hours' , @hours ],
|
137
|
-
['minutes' , @minutes],
|
138
|
-
['seconds' , @seconds]].each do |part, time|
|
139
|
-
|
254
|
+
each do |part, time|
|
140
255
|
# Skip any zero times.
|
141
256
|
next if time.zero?
|
142
257
|
|
@@ -213,12 +328,20 @@ class Duration
|
|
213
328
|
alias to_i total
|
214
329
|
end
|
215
330
|
|
331
|
+
# The following important additions are made to Numeric:
|
332
|
+
#
|
333
|
+
# Numeric#weeks -- Create a Duration object with given weeks
|
334
|
+
# Numeric#days -- Create a Duration object with given days
|
335
|
+
# Numeric#hours -- Create a Duration object with given hours
|
336
|
+
# Numeric#minutes -- Create a Duration object with given minutes
|
337
|
+
# Numeric#seconds -- Create a Duration object with given seconds
|
338
|
+
#
|
216
339
|
class Numeric
|
217
|
-
alias
|
340
|
+
alias __numeric_old_method_missing method_missing
|
218
341
|
|
219
|
-
# Intercept calls to
|
220
|
-
# defines
|
221
|
-
# methods.
|
342
|
+
# Intercept calls to .weeks, .days, .hours, .minutes and .seconds because
|
343
|
+
# Rails defines its own methods, so I'd like to prevent any redefining of
|
344
|
+
# Rails' methods.
|
222
345
|
#
|
223
346
|
# *Example*
|
224
347
|
#
|
@@ -226,14 +349,10 @@ class Numeric
|
|
226
349
|
# => #<Duration: 2 minutes and 20 seconds>
|
227
350
|
#
|
228
351
|
def method_missing(method, *args)
|
229
|
-
|
230
|
-
|
231
|
-
when :days then Duration.new(Duration::DAY * self)
|
232
|
-
when :hours then Duration.new(Duration::HOUR * self)
|
233
|
-
when :minutes then Duration.new(Duration::MINUTE * self)
|
234
|
-
when :seconds then Duration.new(Duration::SECOND * self)
|
352
|
+
if [:weeks, :days, :hours, :minutes, :seconds].include? method
|
353
|
+
Duration.new(method => self)
|
235
354
|
else
|
236
|
-
|
355
|
+
__numeric_old_method_missing(method, *args)
|
237
356
|
end
|
238
357
|
end
|
239
358
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: duration
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date: 2006-05-
|
6
|
+
version: 0.0.3
|
7
|
+
date: 2006-05-24 00:00:00 +09:00
|
8
8
|
summary: Duration is a package for manipulating time spans.
|
9
9
|
require_paths:
|
10
10
|
- lib
|