duration 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/duration.rb +214 -0
  2. 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
+