Skip to content

Instantly share code, notes, and snippets.

@fsubal
Last active June 23, 2024 13:43
Show Gist options
  • Save fsubal/7b176364a6ff8c090cf896656a89aa80 to your computer and use it in GitHub Desktop.
Save fsubal/7b176364a6ff8c090cf896656a89aa80 to your computer and use it in GitHub Desktop.
class PlainTime
include Comparable
attr_reader :hour, :minute, :second
HOUR_PER_DAY = 24
MINUTE_PER_HOUR = 60
SECOND_PER_MINUTE = 60
SECOND_PER_HOUR = HOUR_PER_DAY * MINUTE_PER_HOUR
def initialize(hour, minute, second)
@hour = hour.tap { |h| raise ArgumentError, "hour is #{h}" if h > HOUR_PER_DAY }
@minute = minute.tap { |m| raise ArgumentError, "minute is #{m}" if m > MINUTE_PER_HOUR }
@second = second.tap { |s| raise ArgumentError, "second is #{s}" if s > SECOND_PER_MINUTE }
end
def self.from_second(input_in_second)
hour = input_in_second / SECOND_PER_HOUR
minute = (input_in_second - hour * SECOND_PER_HOUR) / MINUTE_PER_HOUR
second = (input_in_second - hour * SECOND_PER_HOUR - minute * MINUTE_PER_HOUR)
new(hour, minute, second)
end
def am?
hour < 12
end
def pm?
!am?
end
def on(date)
Time.local(date.year, date.month, date.day, hour, minute, second)
end
def +(other)
PlainTime.from_second(self.to_i + other.to_i)
end
def <=>(other)
if hour != other.hour
hour <=> other.hour
elsif minute != other.minute
minute <=> other.minute
elsif second != other.second
second <=> other.second
else
0
end
end
def in_seconds
(hour * SECOND_PER_HOUR) + (minute * SECOND_PER_MINUTE) + second
end
alias to_i in_seconds
def inspect
format(
'%02d:%02d:%02d %s',
hour,
minute,
second,
pm? ? 'PM' : 'AM'
)
end
alias to_s inspect
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment