Class: Tod::TimeOfDay

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/tod/time_of_day.rb

Constant Summary collapse

PARSE_24H_REGEX =
/
  \A
  ([01]?\d|2[0-3])
  :?
  ([0-5]\d)?
  :?
  ([0-5]\d)?
  \z
/x
PARSE_12H_REGEX =
/
  \A
  (0?\d|1[0-2])
  :?
  ([0-5]\d)?
  :?
  ([0-5]\d)?
  \s*
  ([ap])
  \.?
  \s*
  m?
  \.?
  \z
/x
NUM_SECONDS_IN_DAY =
86400
NUM_SECONDS_IN_HOUR =
3600
NUM_SECONDS_IN_MINUTE =
60

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(h, m = 0, s = 0) ⇒ TimeOfDay

Returns a new instance of TimeOfDay.

Raises:

  • (ArgumentError)


40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/tod/time_of_day.rb', line 40

def initialize(h, m=0, s=0)
  @hour = Integer(h)
  @minute = Integer(m)
  @second = Integer(s)

  raise ArgumentError, "hour must be between 0 and 23" unless (0..23).include?(@hour)
  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

Instance Attribute Details

#hourObject (readonly)

Returns the value of attribute hour.



5
6
7
# File 'lib/tod/time_of_day.rb', line 5

def hour
  @hour
end

#minuteObject (readonly) Also known as: min

Returns the value of attribute minute.



5
6
7
# File 'lib/tod/time_of_day.rb', line 5

def minute
  @minute
end

#secondObject (readonly) Also known as: sec

Returns the value of attribute second.



5
6
7
# File 'lib/tod/time_of_day.rb', line 5

def second
  @second
end

#second_of_dayObject (readonly) Also known as: to_i

Returns the value of attribute second_of_day.



5
6
7
# File 'lib/tod/time_of_day.rb', line 5

def second_of_day
  @second_of_day
end

Class Method Details

.dump(time_of_day) ⇒ Object



153
154
155
156
157
158
159
# File 'lib/tod/time_of_day.rb', line 153

def self.dump(time_of_day)
  if time_of_day.to_s == ''
    nil
  else
    time_of_day.to_s
  end
end

.from_second_of_day(second_of_day) ⇒ Object Also known as: from_i

Build a new TimeOfDay instance from second_of_day

TimeOfDay.from_second_of_day(3600) == TimeOfDay.new(1)   # => true


88
89
90
91
92
93
94
95
# File 'lib/tod/time_of_day.rb', line 88

def self.from_second_of_day(second_of_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

.load(time) ⇒ Object



161
162
163
164
165
166
167
# File 'lib/tod/time_of_day.rb', line 161

def self.load(time)
  if time.respond_to?(:to_time_of_day)
    time.to_time_of_day
  else
    TimeOfDay.parse(time) if time && !time.empty?
  end
end

.parsable?(tod_string) ⇒ Boolean

Determine if a string is parsable into a TimeOfDay instance

TimeOfDay.parsable? "8am"                      # => true
TimeOfDay.parsable? "abc"                      # => false

Returns:

  • (Boolean)


144
145
146
# File 'lib/tod/time_of_day.rb', line 144

def self.parsable?(tod_string)
  !!try_parse(tod_string)
end

.parse(tod_string) ⇒ Object

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


115
116
117
# File 'lib/tod/time_of_day.rb', line 115

def self.parse(tod_string)
  try_parse(tod_string) || (raise ArgumentError, "Invalid time of day string")
end

.time_zoneObject

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



149
150
151
# File 'lib/tod/time_of_day.rb', line 149

def self.time_zone
  (Time.respond_to?(:zone) && Time.zone) || Time
end

.try_parse(tod_string) ⇒ Object

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


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

def self.try_parse(tod_string)
  tod_string = tod_string.to_s
  tod_string = tod_string.strip
  tod_string = tod_string.downcase
  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

Instance Method Details

#+(num_seconds) ⇒ Object

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



69
70
71
# File 'lib/tod/time_of_day.rb', line 69

def +(num_seconds)
  TimeOfDay.from_second_of_day @second_of_day + num_seconds
end

#-(num_seconds) ⇒ Object

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



75
76
77
# File 'lib/tod/time_of_day.rb', line 75

def -(num_seconds)
  TimeOfDay.from_second_of_day @second_of_day - num_seconds
end

#<=>(other) ⇒ Object



54
55
56
# File 'lib/tod/time_of_day.rb', line 54

def <=>(other)
  @second_of_day <=> other.second_of_day
end

#on(date, time_zone = Tod::TimeOfDay.time_zone) ⇒ Object

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



81
82
83
# File 'lib/tod/time_of_day.rb', line 81

def on(date, time_zone=Tod::TimeOfDay.time_zone)
  time_zone.local date.year, date.month, date.day, @hour, @minute, @second
end

#strftime(format_string) ⇒ Object

Formats identically to Time#strftime



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

def strftime(format_string)
  Time.local(2000,1,1, @hour, @minute, @second).strftime(format_string)
end

#to_sObject



63
64
65
# File 'lib/tod/time_of_day.rb', line 63

def to_s
  strftime "%H:%M:%S"
end