Class: Period

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/extra/period.rb

Constant Summary collapse

WEEK =
make weeks:   1
DAY =
make days:    1
HOUR =
make hours:   1
MINUTE =
make minutes: 1
SECOND =
make seconds: 1
ZERO =
make seconds: 0

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value) ⇒ Period

Returns a new instance of Period.



10
11
12
# File 'lib/extra/period.rb', line 10

def initialize value
  @value = value
end

Instance Attribute Details

#valueObject (readonly)

Returns the value of attribute value.



8
9
10
# File 'lib/extra/period.rb', line 8

def value
  @value
end

Class Method Details

.diff(first, second) ⇒ Object

Raises:

  • (TypeError)


58
59
60
61
62
63
64
65
# File 'lib/extra/period.rb', line 58

def diff first, second
  first = first.to_time if Date === first
  second = second.to_time if Date === second
  raise TypeError, "Parameter 'first' must be a Time or Date!", caller  unless Time === first
  raise TypeError, "Parameter 'second' must be a Time or Date!", caller unless Time === second
  value = first.to_i - second.to_i
  new(value).freeze
end

.make(weeks: 0, days: 0, hours: 0, minutes: 0, seconds: 0) ⇒ Object

Raises:

  • (TypeError)


44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/extra/period.rb', line 44

def make weeks: 0, days: 0, hours: 0, minutes: 0, seconds: 0
  raise TypeError, "Parameter 'weeks' must be an Integer!", caller   unless Integer === weeks
  raise TypeError, "Parameter 'days' must be an Integer!", caller    unless Integer === days
  raise TypeError, "Parameter 'hours' must be an Integer!", caller   unless Integer === hours
  raise TypeError, "Parameter 'minutes' must be an Integer!", caller unless Integer === minutes
  raise TypeError, "Parameter 'seconds' must be an Integer!", caller unless Integer === seconds
  value =  seconds
  value += minutes             * 60
  value += hours          * 60 * 60
  value += days      * 24 * 60 * 60
  value += weeks * 7 * 24 * 60 * 60
  new(value).freeze
end

.parse(src) ⇒ Object

Raises:

  • (TypeError)


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/extra/period.rb', line 18

def parse src
  return nil if src == nil
  return src if Period === src
  raise TypeError, "Source (#{ src.inspect }) must be a String!", caller unless String === src
  src = src.strip
  value = 0
  case src
  when /^\d+$/
    value = src.to_i
  when /^(\d+[wW])?(\d+[dD])?(\d+[hH])?(\d+[mM])?(\d+[sS])?$/
    weeks = /(\d+)[wW]/.match(src)
    value += weeks[1].to_i * 7 * 24 * 60 * 60 if weeks
    days = /(\d+)[dD]/.match(src)
    value += days[1].to_i * 24 * 60 * 60 if days
    hours = /(\d+)[hH]/.match(src)
    value += hours[1].to_i * 60 * 60 if hours
    minutes = /(\d+)[mM]/.match(src)
    value += minutes[1].to_i * 60 if minutes
    seconds = /(\d+)[sS]/.match(src)
    value += seconds[1].to_i if seconds
  else
    raise ArgumentError, "Invalid source: #{ src }!", caller
  end
  new(value).freeze
end

Instance Method Details

#*(num) ⇒ Object

Raises:

  • (TypeError)


178
179
180
181
# File 'lib/extra/period.rb', line 178

def * num
  raise TypeError, "Second argument must be a number!", caller unless Numeric === num
  self.class.make(seconds: (@value * num).to_i)
end

#+(other) ⇒ Object

Raises:

  • (TypeError)


168
169
170
171
# File 'lib/extra/period.rb', line 168

def + other
  raise TypeError, "Second argument must be a Period!", caller unless Period === other
  self.class.make(seconds: @value + other.value)
end

#+@Object



160
161
162
# File 'lib/extra/period.rb', line 160

def +@
  self
end

#-(other) ⇒ Object

Raises:

  • (TypeError)


173
174
175
176
# File 'lib/extra/period.rb', line 173

def - other
  raise TypeError, "Second argument must be a Period!", caller unless Period === other
  self.class.make(seconds: @value - other.value)
end

#-@Object



164
165
166
# File 'lib/extra/period.rb', line 164

def -@
  self.class.make(seconds: -@value)
end

#/(num) ⇒ Object

Raises:

  • (TypeError)


183
184
185
186
# File 'lib/extra/period.rb', line 183

def / num
  raise TypeError, "Second argument must be a number!", caller unless Numeric === num
  self.class.make(seconds: (@value / num).to_i)
end

#<=>(other) ⇒ Object



155
156
157
158
# File 'lib/extra/period.rb', line 155

def <=> other
  return nil if other.nil?
  @value <=> other.value
end

#absObject



116
117
118
# File 'lib/extra/period.rb', line 116

def abs
  self.class.make seconds: @value.abs
end

#coerce(num) ⇒ Object



205
206
207
208
209
210
211
212
# File 'lib/extra/period.rb', line 205

def coerce num
  case num
  when Integer, Float, Rational
    [ Period::Num::new(num), self ]
  else
    raise TypeError, "Cannot coerce Period to a #{ num.class }!", caller
  end
end

#days(all: true) ⇒ Object



82
83
84
85
86
# File 'lib/extra/period.rb', line 82

def days all: true
  g = sgn
  d = @value.abs / (24 * 60 * 60)
  all && g * d || g * (d % 7)
end

#hours(all: false) ⇒ Object



88
89
90
91
92
# File 'lib/extra/period.rb', line 88

def hours all: false
  g = sgn
  h = @value.abs / (60 * 60)
  all && g * h || g * (h % 24)
end

#inspectObject



149
150
151
# File 'lib/extra/period.rb', line 149

def inspect
  "\#<Period: #{to_s}>"
end

#minutes(all: false) ⇒ Object



94
95
96
97
98
# File 'lib/extra/period.rb', line 94

def minutes all: false
  g = sgn
  m = @value.abs / 60
  all && g * m || g * (m % 60)
end

#seconds(all: false) ⇒ Object



100
101
102
103
104
# File 'lib/extra/period.rb', line 100

def seconds all: false
  g = sgn
  s = @value.abs
  all && g * s || g * (s % 60)
end

#sgnObject



106
107
108
109
110
111
112
113
114
# File 'lib/extra/period.rb', line 106

def sgn
  if @value == 0
    0
  elsif @value > 0
    1
  else
    -1
  end
end

#to_hsObject



141
142
143
144
145
146
147
# File 'lib/extra/period.rb', line 141

def to_hs
  return "-#{abs.to_hs}" if @value < 0
  h = hours all: true
  m = minutes
  s = seconds
  format "%d:%02d:%02d", h, m, s
end

#to_iObject



120
121
122
# File 'lib/extra/period.rb', line 120

def to_i
  @value
end

#to_s(with_weeks: true) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/extra/period.rb', line 124

def to_s with_weeks: true
  return '0' if @value == 0
  return "-#{abs.to_s}" if @value < 0
  w = with_weeks && weeks || 0
  d = days all: !with_weeks
  h = hours
  m = minutes
  s = seconds
  result = ''
  result += "#{ w }w" if w != 0
  result += "#{ d }d" if d != 0
  result += "#{ h }h" if h != 0
  result += "#{ m }m" if m != 0
  result += "#{ s }s" if s != 0
  result
end

#weeksObject



76
77
78
79
80
# File 'lib/extra/period.rb', line 76

def weeks
  g = sgn
  w = @value.abs / (7 * 24 * 60 * 60)
  g * w
end