Class: TimeOfDay
Overview
source: github.com/jackc/tod
Copyright © 2010-2015 Jack Christensen
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Constant Summary collapse
- PARSE_24H_REGEX =
/ \A ([01]?\d|2[0-4]) :? ([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".freeze, "midnight" => "12am".freeze }
- NUM_SECONDS_IN_DAY =
86400- NUM_SECONDS_IN_HOUR =
3600- NUM_SECONDS_IN_MINUTE =
60- FORMATS =
{ short: "%-l:%M %P".freeze, medium: "%-l:%M:%S %P".freeze, time: "%H:%M".freeze }
Instance Attribute Summary collapse
-
#hour ⇒ Object
readonly
Returns the value of attribute hour.
-
#minute ⇒ Object
(also: #min)
readonly
Returns the value of attribute minute.
-
#second ⇒ Object
(also: #sec)
readonly
Returns the value of attribute second.
-
#second_of_day ⇒ Object
(also: #to_i)
readonly
Returns the value of attribute second_of_day.
Class Method Summary collapse
- .dump(time_of_day) ⇒ Object
-
.from_second_of_day(second_of_day) ⇒ Object
(also: from_i)
Build a new TimeOfDay instance from second_of_day.
- .jsoner_deserialize(json_value) ⇒ Object
- .jsoner_serialize(value) ⇒ Object
- .load(time) ⇒ Object
-
.parsable?(tod_string) ⇒ Boolean
Determine if a string is parsable into a TimeOfDay instance TimeOfDay.parsable? “8am” # => true TimeOfDay.parsable? “abc” # => false.
-
.parse(tod_string) ⇒ Object
Build a TimeOfDay instance from string.
-
.time_zone ⇒ Object
If ActiveSupport TimeZone is available and set use current time zone else return Time.
-
.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.
Instance Method Summary collapse
-
#+(num_seconds) ⇒ Object
Return a new TimeOfDay num_seconds greater than self.
-
#-(other) ⇒ Object
Return a new TimeOfDay num_seconds less than self.
- #<=>(other) ⇒ Object
-
#initialize(h, m = 0, s = 0) ⇒ TimeOfDay
constructor
A new instance of TimeOfDay.
-
#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.
-
#round(round_sec = 1) ⇒ Object
Rounding to the given nearest number of seconds.
-
#strftime(format_string) ⇒ Object
Formats identically to Time#strftime.
- #to_formatted_s(format = :default) ⇒ Object (also: #to_s)
- #value_for_database ⇒ Object
Constructor Details
#initialize(h, m = 0, s = 0) ⇒ TimeOfDay
Returns a new instance of TimeOfDay.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/emery/tod.rb', line 84 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 |
Instance Attribute Details
#hour ⇒ Object (readonly)
Returns the value of attribute hour.
38 39 40 |
# File 'lib/emery/tod.rb', line 38 def hour @hour end |
#minute ⇒ Object (readonly) Also known as: min
Returns the value of attribute minute.
38 39 40 |
# File 'lib/emery/tod.rb', line 38 def minute @minute end |
#second ⇒ Object (readonly) Also known as: sec
Returns the value of attribute second.
38 39 40 |
# File 'lib/emery/tod.rb', line 38 def second @second end |
#second_of_day ⇒ Object (readonly) Also known as: to_i
Returns the value of attribute second_of_day.
38 39 40 |
# File 'lib/emery/tod.rb', line 38 def second_of_day @second_of_day end |
Class Method Details
.dump(time_of_day) ⇒ Object
241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/emery/tod.rb', line 241 def self.dump(time_of_day) time_of_day = if time_of_day.is_a? Hash # rails multiparam attribute # get hour, minute and second and construct new TimeOfDay object ::Tod::TimeOfDay.new(time_of_day[4], time_of_day[5], time_of_day[6]) else # return nil, if input is not parsable Tod::TimeOfDay(time_of_day){} end time_of_day.to_s if time_of_day 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
171 172 173 174 175 176 177 178 179 180 |
# File 'lib/emery/tod.rb', line 171 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 |
.jsoner_deserialize(json_value) ⇒ Object
31 32 33 |
# File 'lib/emery/tod.rb', line 31 def self.jsoner_deserialize(json_value) TimeOfDay.parse(T.check(String, json_value)) end |
.jsoner_serialize(value) ⇒ Object
34 35 36 |
# File 'lib/emery/tod.rb', line 34 def self.jsoner_serialize(value) T.check(TimeOfDay, value).to_s end |
.load(time) ⇒ Object
254 255 256 257 258 259 |
# File 'lib/emery/tod.rb', line 254 def self.load(time) if time && !time.to_s.empty? return ::Tod::TimeOfDay.new(24) if time.respond_to?(:day) && time.day == 2 && time.hour == 0 && time.min == 0 && time.sec == 0 ::Tod::TimeOfDay(time) end end |
.parsable?(tod_string) ⇒ Boolean
Determine if a string is parsable into a TimeOfDay instance
TimeOfDay.parsable? "8am" # => true
TimeOfDay.parsable? "abc" # => false
232 233 234 |
# File 'lib/emery/tod.rb', line 232 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
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.
202 203 204 |
# File 'lib/emery/tod.rb', line 202 def self.parse(tod_string) try_parse(tod_string) || (block_given? ? yield(tod_string) : raise(ArgumentError, "Invalid time of day string")) end |
.time_zone ⇒ Object
If ActiveSupport TimeZone is available and set use current time zone else return Time
237 238 239 |
# File 'lib/emery/tod.rb', line 237 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
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/emery/tod.rb', line 210 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.
148 149 150 |
# File 'lib/emery/tod.rb', line 148 def +(num_seconds) TimeOfDay.from_second_of_day @second_of_day + num_seconds end |
#-(other) ⇒ Object
Return a new TimeOfDay num_seconds less than self. It will wrap around at midnight.
154 155 156 157 158 159 160 |
# File 'lib/emery/tod.rb', line 154 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) ⇒ Object
101 102 103 104 |
# File 'lib/emery/tod.rb', line 101 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
164 165 166 |
# File 'lib/emery/tod.rb', line 164 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) ⇒ Object
Rounding to the given nearest number of seconds
107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/emery/tod.rb', line 107 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) ⇒ Object
Formats identically to Time#strftime
122 123 124 125 126 127 |
# File 'lib/emery/tod.rb', line 122 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) ⇒ Object Also known as: to_s
129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/emery/tod.rb', line 129 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 |
#value_for_database ⇒ Object
142 143 144 |
# File 'lib/emery/tod.rb', line 142 def value_for_database to_s end |