Class: RichUnits::Duration

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/richunits/duration.rb

Overview

Durations

Defined Under Namespace

Modules: Numeric, Time

Constant Summary collapse

SECOND =
1
MINUTE =
60 * SECOND
HOUR =
60 * MINUTE
DAY =
24 * HOUR
WEEK =
7 * DAY
YEAR =
365 * DAY
SEGMENTS =
%w{years weeks days hours minutes seconds}.collect{ |s| s.to_sym }

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(seconds = 0, segmentA = nil, segmentB = nil) ⇒ Duration

New duration.

call-seq:
  new(seconds)
  new(seconds, max-period)
  new(seconds, max-period, min-period)
  new(seconds, [period1, period2, ...])


31
32
33
34
# File 'lib/richunits/duration.rb', line 31

def initialize(seconds=0, segmentA=nil, segmentB=nil)
  @seconds = seconds.to_i
  reset_segments(segmentA, segmentB)
end

Class Method Details

.[](seconds, segmentA = nil, segmentB = nil) ⇒ Object

Same as #new



19
20
21
# File 'lib/richunits/duration.rb', line 19

def self.[](seconds, segmentA=nil, segmentB=nil)
  new(seconds, segmentA, segmentB)
end

Instance Method Details

#*(other) ⇒ Object



148
149
150
# File 'lib/richunits/duration.rb', line 148

def *(other)
  self.class.new(@seconds * other.to_i, segments)
end

#+(other) ⇒ Object



140
141
142
# File 'lib/richunits/duration.rb', line 140

def +(other)
  self.class.new(@seconds + other.to_i, segments)
end

#+@Object

:nodoc:



214
215
216
# File 'lib/richunits/duration.rb', line 214

def +@ #:nodoc:
  self.class.new(+@seconds)
end

#-(other) ⇒ Object



144
145
146
# File 'lib/richunits/duration.rb', line 144

def -(other)
  self.class.new(@seconds - other.to_i, segments)
end

#-@Object

:nodoc:



209
210
211
# File 'lib/richunits/duration.rb', line 209

def -@ #:nodoc:
  self.class.new(-@seconds)
end

#/(other) ⇒ Object



152
153
154
# File 'lib/richunits/duration.rb', line 152

def /(other)
  self.class.new(@seconds / other.to_i, segments)
end

#<=>(other) ⇒ Object



119
120
121
# File 'lib/richunits/duration.rb', line 119

def <=>(other)
  @seconds <=> other.to_i
end

#==(other) ⇒ Object

Returns true if other is also a Duration instance with the same value, or if other == value.



111
112
113
114
115
116
117
# File 'lib/richunits/duration.rb', line 111

def ==(other)
  if Duration === other
    other.seconds == seconds
  else
    other == seconds
  end
end

#after(time) ⇒ Object



228
229
230
# File 'lib/richunits/duration.rb', line 228

def after(time)
  @seconds.after(time)
end

#before(time) ⇒ Object



223
224
225
# File 'lib/richunits/duration.rb', line 223

def before(time)
  @seconds.before(time)
end

#daysObject



133
# File 'lib/richunits/duration.rb', line 133

def days    ; to_h[:days]    ; end

#hoursObject



134
# File 'lib/richunits/duration.rb', line 134

def hours   ; to_h[:hours]   ; end

#inspectObject



65
66
67
68
69
70
# File 'lib/richunits/duration.rb', line 65

def inspect
  h = to_h
  segments.reverse.collect do |l|
    "#{h[l.to_sym]} #{l}"
  end.join(' ')
end

#minutesObject



135
# File 'lib/richunits/duration.rb', line 135

def minutes ; to_h[:minutes] ; end

#reset_segments(segmentA = nil, segmentB = nil) ⇒ Object

Reset segments.

call-seq:
  reset_segments(max-period)
  reset_segments(max-period, min-period)
  reset_segments([period1, period2, ...])


46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/richunits/duration.rb', line 46

def reset_segments(segmentA=nil, segmentB=nil)
  if !segmentA
    @segments = [:days, :hours, :minutes, :seconds]
  elsif !segmentB
    case segmentA
    when Array
      @segments = segmentA.map{ |p| (p.to_s.downcase.chomp('s') + 's').to_sym }
      raise ArgumentError unless @segments.all?{ |s| SEGMENTS.include?(s) }
    else
      f = SEGMENTS.index(segmentA)
      @segments = SEGMENTS[f..0]
    end
  else # segmentA && segmentB
    f = SEGMENTS.index(segmentA)
    t = SEGMENTS.index(segmentB)
    @segments = SEGMENTS[f..t]
  end
end

#secondsObject



136
# File 'lib/richunits/duration.rb', line 136

def seconds ; to_h[:seconds] ; end

#segmented(*segments) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/richunits/duration.rb', line 157

def segmented(*segments)
  self.class.new(@seconds, segments)
  #segments = segments.collect{ |p| p.to_s.downcase.chomp('s') }
  #y,w,d,h,m,s = nil,nil,nil,nil,nil,nil
  #x = @seconds
  #y, x = *x.divmod(YEAR)   if segments.include?('year')
  #w, x = *x.divmod(WEEK)   if segments.include?('week')
  #d, x = *x.divmod(DAY)    if segments.include?('day')
  #h, x = *x.divmod(HOUR)   if segments.include?('hour')
  #m, x = *x.divmod(MINUTE) if segments.include?('minute')
  #s = x if segments.include?('second')
  #[y, w, d, h, m, s].compact
end

#segmentsObject

List of period segments.



37
# File 'lib/richunits/duration.rb', line 37

def segments; @segments; end

#strftime(fmt) ⇒ Object

Format duration.

Identifiers

%w -- Number of weeks
%d -- Number of days
%h -- Number of hours
%m -- Number of minutes
%s -- Number of seconds
%t -- Total number of seconds
%x -- Duration#to_s
%% -- Literal `%' character

Example

d = Duration.new(:weeks => 10, :days => 7)
=> #<Duration: 11 weeks>
d.strftime("It's been %w weeks!")
=> "It's been 11 weeks!"


191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/richunits/duration.rb', line 191

def strftime(fmt)
  h = to_h
  hx = {
   'y' => h[:years]  ,
   'w' => h[:weeks]  ,
   'd' => h[:days]   ,
   'h' => h[:hours]  ,
   'm' => h[:minutes],
   's' => h[:seconds],
   't' => total,
   'x' => to_s 
  }
  fmt.gsub(/%?%(w|d|h|m|s|t|x)/) do |match|
    hx[match[1..1]]
  end.gsub('%%', '%')
end

#to_aObject



79
80
81
82
83
84
85
86
87
88
# File 'lib/richunits/duration.rb', line 79

def to_a
  a, s = [], @seconds
  a[5], s = *s.divmod(YEAR)   if @segments.include?(:years)
  a[4], s = *s.divmod(WEEK)   if @segments.include?(:weeks)
  a[3], s = *s.divmod(DAY)    if @segments.include?(:days)
  a[2], s = *s.divmod(HOUR)   if @segments.include?(:hours)
  a[1], s = *s.divmod(MINUTE) if @segments.include?(:minutes)
  a[0], s = *s.divmod(SECOND) if @segments.include?(:seconds)
  a.compact.reverse
end

#to_fObject



73
# File 'lib/richunits/duration.rb', line 73

def to_f ; @seconds.to_f ; end

#to_hObject



91
92
93
94
95
96
97
98
99
100
# File 'lib/richunits/duration.rb', line 91

def to_h
  h, s = {}, @seconds
  h[:years],   s = *s.divmod(YEAR)   if @segments.include?(:years)
  h[:weeks],   s = *s.divmod(WEEK)   if @segments.include?(:weeks)
  h[:days],    s = *s.divmod(DAY)    if @segments.include?(:days)
  h[:hours],   s = *s.divmod(HOUR)   if @segments.include?(:hours)
  h[:minutes], s = *s.divmod(MINUTE) if @segments.include?(:minutes)
  h[:seconds], s = *s.divmod(SECOND) if @segments.include?(:seconds)
  h
end

#to_iObject Also known as: to_int



72
# File 'lib/richunits/duration.rb', line 72

def to_i ; @seconds.to_i ; end

#to_sObject



102
103
104
105
106
107
# File 'lib/richunits/duration.rb', line 102

def to_s
  h = to_h
  segments.reverse.collect do |l|
    "#{h[l.to_sym]} #{l}"
  end.join(' ')
end

#totalObject



138
# File 'lib/richunits/duration.rb', line 138

def total ; seconds ; end

#weeksObject



132
# File 'lib/richunits/duration.rb', line 132

def weeks   ; to_h[:weeks]   ; end

#yearsObject

def self.===(other) #:nodoc:

other.is_a?(Duration) rescue super

end



131
# File 'lib/richunits/duration.rb', line 131

def years   ; to_h[:years]   ; end