class Tod::TimeOfDay

Constants

FORMATS
NUM_SECONDS_IN_DAY
NUM_SECONDS_IN_HOUR
NUM_SECONDS_IN_MINUTE
PARSE_12H_REGEX
PARSE_24H_REGEX
WORDS

Attributes

hour[R]
min[R]
minute[R]
sec[R]
second[R]
second_of_day[R]
to_i[R]

Public Class Methods

from_i(second_of_day)
Alias for: from_second_of_day
from_second_of_day(second_of_day) click to toggle source

Build a new TimeOfDay instance from second_of_day

TimeOfDay.from_second_of_day(3600) == TimeOfDay.new(1)   # => true
# File lib/tod/time_of_day.rb, line 138
def self.from_second_of_day(second_of_day)
  second_of_day = Integer(second_of_day)
  return new 24 if second_of_day == NUM_SECONDS_IN_DAY
  remaining_seconds = second_of_day % NUM_SECONDS_IN_DAY
  hour = remaining_seconds / NUM_SECONDS_IN_HOUR
  remaining_seconds -= hour * NUM_SECONDS_IN_HOUR
  minute = remaining_seconds / NUM_SECONDS_IN_MINUTE
  remaining_seconds -= minute * NUM_SECONDS_IN_MINUTE
  new hour, minute, remaining_seconds
end
Also aliased as: from_i
new(h, m=0, s=0) click to toggle source
# File lib/tod/time_of_day.rb, line 51
def initialize(h, m=0, s=0)
  @hour = Integer(h)
  @minute = Integer(m)
  @second = Integer(s)

  raise ArgumentError, "hour must be between 0 and 24" unless (0..24).include?(@hour)
  if @hour == 24 && (@minute != 0 || @second != 0)
    raise ArgumentError, "hour can only be 24 when minute and second are 0"
  end
  raise ArgumentError, "minute must be between 0 and 59" unless (0..59).include?(@minute)
  raise ArgumentError, "second must be between 0 and 59" unless (0..59).include?(@second)

  @second_of_day = @hour * 60 * 60 + @minute * 60 + @second

  freeze # TimeOfDay instances are value objects
end
parsable?(tod_string) click to toggle source

Determine if a string is parsable into a TimeOfDay instance

TimeOfDay.parsable? "8am"                      # => true
TimeOfDay.parsable? "abc"                      # => false
# File lib/tod/time_of_day.rb, line 199
def self.parsable?(tod_string)
  !!try_parse(tod_string)
end
parse(tod_string) { |tod_string| ... } click to toggle source

Build a TimeOfDay instance from string

Strings only need to contain an hour. Minutes, seconds, AM or PM, and colons are all optional.

TimeOfDay.parse "8"                            # => 08:00:00
TimeOfDay.parse "8am"                          # => 08:00:00
TimeOfDay.parse "8pm"                          # => 20:00:00
TimeOfDay.parse "8p"                           # => 20:00:00
TimeOfDay.parse "9:30"                         # => 09:30:00
TimeOfDay.parse "15:30"                        # => 15:30:00
TimeOfDay.parse "3:30pm"                       # => 15:30:00
TimeOfDay.parse "1230"                         # => 12:30:00
TimeOfDay.parse "3:25:58"                      # => 03:25:58
TimeOfDay.parse "515p"                         # => 17:15:00
TimeOfDay.parse "151253"                       # => 15:12:53

You can give a block, that is called with the input if the string is not parsable. If no block is given an ArgumentError is raised if try_parse returns nil.

# File lib/tod/time_of_day.rb, line 169
def self.parse(tod_string)
  try_parse(tod_string) || (block_given? ? yield(tod_string) : raise(ArgumentError, "Invalid time of day string"))
end
time_zone() click to toggle source

If ActiveSupport TimeZone is available and set use current time zone else return Time

# File lib/tod/time_of_day.rb, line 204
def self.time_zone
  (Time.respond_to?(:zone) && Time.zone) || Time
end
try_parse(tod_string) click to toggle source

Same as parse(), but return nil if not parsable (instead of raising an error)

TimeOfDay.try_parse "8am"                      # => 08:00:00
TimeOfDay.try_parse ""                         # => nil
TimeOfDay.try_parse "abc"                      # => nil
# File lib/tod/time_of_day.rb, line 177
def self.try_parse(tod_string)
  tod_string = tod_string.to_s
  tod_string = tod_string.strip
  tod_string = tod_string.downcase
  tod_string = WORDS[tod_string] || tod_string
  if PARSE_24H_REGEX =~ tod_string || PARSE_12H_REGEX =~ tod_string
    hour, minute, second, a_or_p = $1.to_i, $2.to_i, $3.to_i, $4
    if hour == 12 && a_or_p == "a"
      hour = 0
    elsif hour < 12 && a_or_p == "p"
      hour += 12
    end

    new hour, minute, second
  else
    nil
  end
end

Public Instance Methods

+(num_seconds) click to toggle source

Return a new TimeOfDay num_seconds greater than self. It will wrap around at midnight.

# File lib/tod/time_of_day.rb, line 115
def +(num_seconds)
  TimeOfDay.from_second_of_day @second_of_day + num_seconds
end
-(other) click to toggle source

Return a new TimeOfDay num_seconds less than self. It will wrap around at midnight.

# File lib/tod/time_of_day.rb, line 121
def -(other)
  if other.instance_of?(TimeOfDay)
    TimeOfDay.from_second_of_day @second_of_day - other.second_of_day
  else
    TimeOfDay.from_second_of_day @second_of_day - other
  end
end
<=>(other) click to toggle source
# File lib/tod/time_of_day.rb, line 68
def <=>(other)
  return unless other.respond_to?(:second_of_day)
  @second_of_day <=> other.second_of_day
end
on(date, time_zone=Tod::TimeOfDay.time_zone) click to toggle source

Returns a Time instance on date using self as the time of day Optional time_zone will build time in that zone

# File lib/tod/time_of_day.rb, line 131
def on(date, time_zone=Tod::TimeOfDay.time_zone)
  time_zone.local date.year, date.month, date.day, @hour, @minute, @second
end
round(round_sec = 1) click to toggle source

Rounding to the given nearest number of seconds

# File lib/tod/time_of_day.rb, line 74
def round(round_sec = 1)
  down = self - (self.to_i % round_sec)
  up = down + round_sec

  difference_down = self - down
  difference_up = up - self

  if (difference_down < difference_up)
    return down
  else
    return up
  end
end
strftime(format_string) click to toggle source

Formats identically to Time#strftime

# File lib/tod/time_of_day.rb, line 89
def strftime(format_string)
  # Special case 2400 because strftime will load TimeOfDay into Time which
  # will convert 24 to 0
  format_string = format_string.gsub(/%H|%k/, '24') if @hour == 24
  Time.local(2000,1,1, @hour, @minute, @second).strftime(format_string)
end
to_formatted_s(format = :default) click to toggle source
# File lib/tod/time_of_day.rb, line 96
def to_formatted_s(format = :default)
  if formatter = FORMATS[format]
    if formatter.respond_to?(:call)
      formatter.call(self).to_s
    else
      strftime(formatter)
    end
  else
    strftime "%H:%M:%S"
  end
end
Also aliased as: to_s
to_s(format = :default)
Alias for: to_formatted_s
value_for_database() click to toggle source
# File lib/tod/time_of_day.rb, line 109
def value_for_database
  to_s
end