duration 0.0.1
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 +214 -0
- metadata +45 -0
data/lib/duration.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
# = Author
|
2
|
+
#
|
3
|
+
# Matthew Harris (mailto:shugotenshi@gmail.com)
|
4
|
+
#
|
5
|
+
# = Project
|
6
|
+
#
|
7
|
+
# http://www.rubyforge.org/projects/duration
|
8
|
+
#
|
9
|
+
# = Synopsis
|
10
|
+
#
|
11
|
+
# Duration is a simple class that provides ways of easily manipulating durations
|
12
|
+
# (timespans) and formatting them as well.
|
13
|
+
#
|
14
|
+
# = Usage
|
15
|
+
#
|
16
|
+
# require 'duration'
|
17
|
+
# => true
|
18
|
+
# d = Duration.new(60 * 60 * 24 * 10 + 120 + 30)
|
19
|
+
# => #<Duration: 1 week, 3 days, 2 minutes and 30 seconds>
|
20
|
+
# d.to_s
|
21
|
+
# => "1 week, 3 days, 2 minutes and 30 seconds"
|
22
|
+
# [d.weeks, d.days]
|
23
|
+
# => [1, 3]
|
24
|
+
# d.days = 7; d
|
25
|
+
# => #<Duration: 2 weeks, 2 minutes and 30 seconds>
|
26
|
+
# d.strftime('%w w, %d d, %h h, %m m, %s s')
|
27
|
+
# => "2 w, 0 d, 0 h, 2 m, 30 s"
|
28
|
+
#
|
29
|
+
class Duration
|
30
|
+
attr_reader :total, :weeks, :days, :hours, :minutes, :seconds
|
31
|
+
|
32
|
+
WEEK = 60 * 60 * 24 * 7
|
33
|
+
DAY = 60 * 60 * 24
|
34
|
+
HOUR = 60 * 60
|
35
|
+
MINUTE = 60
|
36
|
+
SECOND = 1
|
37
|
+
|
38
|
+
# Initialize Duration class.
|
39
|
+
#
|
40
|
+
# *Example*
|
41
|
+
#
|
42
|
+
# d = Duration.new(60 * 60 * 24 * 10 + 120 + 30)
|
43
|
+
# => #<Duration: 1 week, 3 days, 2 minutes and 30 seconds>
|
44
|
+
#
|
45
|
+
# d = Duration.new(:weeks => 1, :days => 3, :minutes => 2, :seconds => 30)
|
46
|
+
# => #<Duration: 1 week, 3 days, 2 minutes and 30 seconds>
|
47
|
+
#
|
48
|
+
def initialize(seconds_or_attr)
|
49
|
+
if (h = seconds_or_attr).kind_of? Hash
|
50
|
+
seconds = 0
|
51
|
+
seconds += h[:weeks] * WEEK if h.key? :weeks
|
52
|
+
seconds += h[:days] * DAY if h.key? :days
|
53
|
+
seconds += h[:hours] * HOUR if h.key? :hours
|
54
|
+
seconds += h[:minutes] * MINUTE if h.key? :minutes
|
55
|
+
seconds += h[:seconds] * SECOND if h.key? :seconds
|
56
|
+
else
|
57
|
+
seconds = seconds_or_attr
|
58
|
+
end
|
59
|
+
|
60
|
+
@total, array = seconds.to_f.round, []
|
61
|
+
@seconds = [WEEK, DAY, HOUR, MINUTE].inject(@total) do |left, part|
|
62
|
+
array << left / part; left % part
|
63
|
+
end
|
64
|
+
|
65
|
+
@weeks, @days, @hours, @minutes = array
|
66
|
+
end
|
67
|
+
|
68
|
+
# Format duration.
|
69
|
+
#
|
70
|
+
# *Identifiers*
|
71
|
+
#
|
72
|
+
# %w - Number of weeks
|
73
|
+
# %d - Number of days
|
74
|
+
# %h - Number of hours
|
75
|
+
# %m - Number of minutes
|
76
|
+
# %s - Number of seconds
|
77
|
+
# %% - Literal `%' character
|
78
|
+
#
|
79
|
+
# *Example*
|
80
|
+
#
|
81
|
+
# d = Duration.new(:weeks => 10, :days => 7)
|
82
|
+
# => #<Duration: 11 weeks>
|
83
|
+
# d.strftime("It's been %w weeks!")
|
84
|
+
# => "It's been 11 weeks!"
|
85
|
+
#
|
86
|
+
def strftime(fmt)
|
87
|
+
h =\
|
88
|
+
{'w' => @weeks ,
|
89
|
+
'd' => @days ,
|
90
|
+
'h' => @hours ,
|
91
|
+
'm' => @minutes,
|
92
|
+
's' => @seconds}
|
93
|
+
|
94
|
+
fmt.gsub(/%?%(w|d|h|m|s)/) do |match|
|
95
|
+
match.size == 3 ? match : h[match[1..1]]
|
96
|
+
end.gsub('%%', '%')
|
97
|
+
end
|
98
|
+
|
99
|
+
# Intercept certain attribute writers. Intercepts `weeks=', `days=', `hours=',
|
100
|
+
# `minutes=', `seconds=', and `total='
|
101
|
+
#
|
102
|
+
# *Example*
|
103
|
+
#
|
104
|
+
# d = Duration.new(:days => 6)
|
105
|
+
# => #<Duration: 6 days>
|
106
|
+
# d.days += 1; d
|
107
|
+
# => #<Duration: 1 week>
|
108
|
+
#
|
109
|
+
def method_missing(method, *args)
|
110
|
+
case method
|
111
|
+
when :weeks= then initialize(WEEK * args[0] + (@total - WEEK * @weeks ))
|
112
|
+
when :days= then initialize(DAY * args[0] + (@total - DAY * @days ))
|
113
|
+
when :hours= then initialize(HOUR * args[0] + (@total - HOUR * @hours ))
|
114
|
+
when :minutes= then initialize(MINUTE * args[0] + (@total - MINUTE * @minutes))
|
115
|
+
when :seconds= then initialize(SECOND * args[0] + (@total - SECOND * @seconds))
|
116
|
+
when :total= then initialize(args[0])
|
117
|
+
else
|
118
|
+
raise NoMethodError, "undefined method `#{method}' for #{inspect}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Friendly, human-readable string representation of the duration.
|
123
|
+
#
|
124
|
+
# *Example*
|
125
|
+
#
|
126
|
+
# d = Duration.new(:seconds => 140)
|
127
|
+
# => #<Duration: 2 minutes and 20 seconds>
|
128
|
+
# d.to_s
|
129
|
+
# => "2 minutes and 20 seconds"
|
130
|
+
#
|
131
|
+
def to_s
|
132
|
+
str = ''
|
133
|
+
|
134
|
+
[['weeks' , @weeks ],
|
135
|
+
['days' , @days ],
|
136
|
+
['hours' , @hours ],
|
137
|
+
['minutes' , @minutes],
|
138
|
+
['seconds' , @seconds]].each do |part, time|
|
139
|
+
|
140
|
+
# Skip any zero times.
|
141
|
+
next if time.zero?
|
142
|
+
|
143
|
+
# Concatenate the part of the time and the time itself.
|
144
|
+
str << "#{time} #{time == 1 ? part[0..-2] : part}, "
|
145
|
+
end
|
146
|
+
|
147
|
+
str.chomp(', ').sub(/(.+), (.+)/, '\1 and \2')
|
148
|
+
end
|
149
|
+
|
150
|
+
# Inspection string--Similar to #to_s except that it has the class name.
|
151
|
+
#
|
152
|
+
# *Example*
|
153
|
+
#
|
154
|
+
# Duration.new(:seconds => 140)
|
155
|
+
# => #<Duration: 2 minutes and 20 seconds>
|
156
|
+
#
|
157
|
+
def inspect
|
158
|
+
"#<#{self.class}: #{(s = to_s).empty? ? '...' : s}>"
|
159
|
+
end
|
160
|
+
|
161
|
+
# Add to Duration.
|
162
|
+
#
|
163
|
+
# *Example*
|
164
|
+
#
|
165
|
+
# d = Duration.new(30)
|
166
|
+
# => #<Duration: 30 seconds>
|
167
|
+
# d + 30
|
168
|
+
# => #<Duration: 1 minute>
|
169
|
+
#
|
170
|
+
def +(other)
|
171
|
+
self.class.new(@total + other.to_i)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Subtract from Duration.
|
175
|
+
#
|
176
|
+
# *Example*
|
177
|
+
#
|
178
|
+
# d = Duration.new(30)
|
179
|
+
# => #<Duration: 30 seconds>
|
180
|
+
# d - 15
|
181
|
+
# => #<Duration: 15 seconds>
|
182
|
+
#
|
183
|
+
def -(other)
|
184
|
+
self.class.new(@total - other.to_i)
|
185
|
+
end
|
186
|
+
|
187
|
+
# Multiply two Durations.
|
188
|
+
#
|
189
|
+
# *Example*
|
190
|
+
#
|
191
|
+
# d = Duration.new(30)
|
192
|
+
# => #<Duration: 30 seconds>
|
193
|
+
# d * 2
|
194
|
+
# => #<Duration: 1 minute>
|
195
|
+
#
|
196
|
+
def *(other)
|
197
|
+
self.class.new(@total * other.to_i)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Divide two Durations.
|
201
|
+
#
|
202
|
+
# *Example*
|
203
|
+
#
|
204
|
+
# d = Duration.new(30)
|
205
|
+
# => #<Duration: 30 seconds>
|
206
|
+
# d / 2
|
207
|
+
# => #<Duration: 15 seconds>
|
208
|
+
#
|
209
|
+
def /(other)
|
210
|
+
self.class.new(@total / other.to_i)
|
211
|
+
end
|
212
|
+
|
213
|
+
alias to_i total
|
214
|
+
end
|
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: duration
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2006-05-23 00:00:00 +09:00
|
8
|
+
summary: Duration is a package for manipulating time spans.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: shugotenshi@gmail.com
|
12
|
+
homepage: http://duration.rubyforge.org
|
13
|
+
rubyforge_project: duration
|
14
|
+
description: Duration is a simple class that provides ways of easily manipulating durations (timespans) and formatting them as well.
|
15
|
+
autorequire: duration
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
authors:
|
29
|
+
- Matthew Harris
|
30
|
+
files:
|
31
|
+
- lib/duration.rb
|
32
|
+
test_files: []
|
33
|
+
|
34
|
+
rdoc_options: []
|
35
|
+
|
36
|
+
extra_rdoc_files: []
|
37
|
+
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
requirements: []
|
43
|
+
|
44
|
+
dependencies: []
|
45
|
+
|