Class: Hour

Inherits:
Object
  • Object
show all
Defined in:
lib/hour.rb

Defined Under Namespace

Classes: HourUnit, MinuteUnit, SecondUnit, Unit

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Hour

Build an hour instance from h, m and s. Raises an argument error if m or s is a value over 60.

For instantiating this class from a minutes or seconds value over 60, use ‘.from`.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/hour.rb', line 111

def initialize(*args)
  if args.length == 1 && args.first.is_a?(Hash)
    initialize_from_keyword_args(**args.first)
  else
    # Pad with 0s.
    args = args + Array.new(3 - args.length, 0)
    @h, @m, @s = args
  end

  if @m > 60
    raise ArgumentError.new("Minutes must be a number between 0 and 60.")
  end

  if @s > 60
    raise ArgumentError.new("Seconds must be a number between 0 and 60.")
  end
end

Instance Attribute Details

#hObject (readonly)

Returns the value of attribute h.



105
106
107
# File 'lib/hour.rb', line 105

def h
  @h
end

#mObject (readonly)

Returns the value of attribute m.



105
106
107
# File 'lib/hour.rb', line 105

def m
  @m
end

#sObject (readonly)

Returns the value of attribute s.



105
106
107
# File 'lib/hour.rb', line 105

def s
  @s
end

Class Method Details

.from(minutes: 0, seconds: 0) ⇒ Object

Build an hour instance from either minutes or seconds. Unlike ‘.new`, either of these values can be over 60.

Hour.from(minutes: 85)  # => Hour.new(h: 1, m: 25)
Hour.from(seconds: 120) # => Hour.new(m: 2)


93
94
95
96
97
98
99
100
101
102
103
# File 'lib/hour.rb', line 93

def self.from(minutes: 0, seconds: 0)
  if minutes != 0 && seconds != 0
    raise ArgumentError.new("Use either minutes OR seconds, not both.")
  end

  if minutes > 0
    self.new(h: minutes / 60, m: minutes % 60)
  else
    self.from(minutes: seconds / 60) + self.new(s: seconds % 60)
  end
end

.from_time(time) ⇒ Object

TODO: document and write tests.



64
65
66
# File 'lib/hour.rb', line 64

def self.from_time(time)
  self.new(time.hour, time.min, time.sec)
end

.nowObject

TODO: Test me and document me.



59
60
61
# File 'lib/hour.rb', line 59

def self.now
  self.from_time(Time.now)
end

.parse(serialised_hour, formatting_string = nil) ⇒ Object

Build an hour instance from an hour string.

Hour.parse("1:00:00")
Hour.parse("1:00", "%h:%m?") # Will work with "1:00" or just "1".

TODO: Implement me, test me and document me.



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/hour.rb', line 74

def self.parse(serialised_hour, formatting_string = nil)
  args = serialised_hour.split(':').map(&:to_i)

  case args.length
  when 3
    self.new(*args)
  when (0..2)
    # TODO: if formatting_string ...
    raise ArgumentError.new("If format is not H:M:S, formatting string must be provided.")
  when (4..Float::INFINITY) # Until we have infinite ranges like (4..) in Ruby 2.6.
    raise ArgumentError, "Too many arguments."
  end
end

Instance Method Details

#+(other) ⇒ Object

Returns a new Hour instance returning the total time of the two hour instances.

Hour.new(m: 25, s: 10) + Hour.new(h: 1) # => Hour.new(1, 25, 10)


132
133
134
135
136
137
# File 'lib/hour.rb', line 132

def +(other)
  hours = @h + other.h + (@m + other.m + ((@s + other.s) / 60)) / 60
  minutes = (@m + other.m + ((@s + other.s) / 60)) % 60
  seconds = (@s + other.s) % 60
  self.class.new(hours, minutes, seconds)
end

#hoursObject

Returns a decorator providing convenience methods for working with hours.

Hour.new(1, 25).hours.round # => 1
Hour.new(1, 45).hours.round # => 2


143
144
145
# File 'lib/hour.rb', line 143

def hours
  HourUnit.new(self)
end

#minutesObject

Returns a decorator providing convenience methods for working with minutes.

Hour.new(1, 25, 52).minutes.value       # => 25
Hour.new(1, 25, 52).minutes.round       # => 26
Hour.new(1, 25, 52).minutes.total       # => 85
Hour.new(1, 25, 52).minutes.round_total # => 86


153
154
155
# File 'lib/hour.rb', line 153

def minutes
  MinuteUnit.new(self)
end

#secondsObject

Returns a decorator providing convenience methods for working with seconds.

Hour.new(m: 1, s: 10).seconds.value # => 10
Hour.new(1, 45, 10  ).seconds.total # => (1 * 60 * 60) + (45 * 60) + 10


161
162
163
# File 'lib/hour.rb', line 161

def seconds
  SecondUnit.new(self)
end

#to_s(format = nil) ⇒ Object Also known as: inspect

TODO: Add formatting string support. TODO: Pad 0s. I. e. “#Hour.selfself.hours:#self.minutes_over_the_hour)”



167
168
169
# File 'lib/hour.rb', line 167

def to_s(format = nil)
  "#{@h}:#{@m}:#{@s}"
end

#to_time(today = Time.now) ⇒ Object



173
174
175
# File 'lib/hour.rb', line 173

def to_time(today = Time.now)
  Time.new(today.year, today.month, today.day, self.hours, self.minutes_over_the_hour)
end