Class: Tod::TimeOfDay

Inherits:
Object
  • Object
show all
Extended by:
Mongoization::ClassMethods
Includes:
Comparable, Mongoization
Defined in:
lib/tod/time_of_day.rb,
lib/tod/mongoization.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
WORDS =
{
  "noon" => "12pm",
  "midnight" => "12am"
}
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

Methods included from Mongoization::ClassMethods

demongoize, evolve, mongoize

Methods included from Mongoization

#mongoize

Constructor Details

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

Returns a new instance of TimeOfDay.

Raises:

  • (ArgumentError)

45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/tod/time_of_day.rb', line 45

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


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

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

94
95
96
97
98
99
100
101
# File 'lib/tod/time_of_day.rb', line 94

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


168
169
170
# File 'lib/tod/time_of_day.rb', line 168

def self.load(time)
  ::Tod::TimeOfDay(time) if time && !time.to_s.empty?
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)

151
152
153
# File 'lib/tod/time_of_day.rb', line 151

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

121
122
123
# File 'lib/tod/time_of_day.rb', line 121

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


156
157
158
# File 'lib/tod/time_of_day.rb', line 156

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

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/tod/time_of_day.rb', line 129

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

Instance Method Details

#+(num_seconds) ⇒ Object

Return a new TimeOfDay num_seconds greater 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

#-(num_seconds) ⇒ Object

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


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

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

#<=>(other) ⇒ Object


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

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) ⇒ Object

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


87
88
89
# File 'lib/tod/time_of_day.rb', line 87

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


65
66
67
# File 'lib/tod/time_of_day.rb', line 65

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

#to_sObject


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

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