emery 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/emery/tod.rb CHANGED
@@ -25,238 +25,236 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
25
 
26
26
  =end
27
27
 
28
- module Emery
29
- class TimeOfDay
30
- include Comparable
28
+ class TimeOfDay
29
+ include Comparable
31
30
 
32
- def self.jsoner_deserialize(json_value)
33
- TimeOfDay.parse(T.check(String, json_value))
34
- end
35
- def self.jsoner_serialize(value)
36
- T.check(TimeOfDay, value).to_s
37
- end
31
+ def self.jsoner_deserialize(json_value)
32
+ TimeOfDay.parse(T.check(String, json_value))
33
+ end
34
+ def self.jsoner_serialize(value)
35
+ T.check(TimeOfDay, value).to_s
36
+ end
38
37
 
39
- attr_reader :hour, :minute, :second, :second_of_day
40
- alias_method :min, :minute
41
- alias_method :sec, :second
42
- alias_method :to_i, :second_of_day
43
-
44
- PARSE_24H_REGEX = /
45
- \A
46
- ([01]?\d|2[0-4])
47
- :?
48
- ([0-5]\d)?
49
- :?
50
- ([0-5]\d)?
51
- \z
52
- /x
53
-
54
- PARSE_12H_REGEX = /
55
- \A
56
- (0?\d|1[0-2])
57
- :?
58
- ([0-5]\d)?
59
- :?
60
- ([0-5]\d)?
61
- \s*
62
- ([ap])
63
- \.?
64
- \s*
65
- m?
66
- \.?
67
- \z
68
- /x
69
-
70
- WORDS = {
71
- "noon" => "12pm".freeze,
72
- "midnight" => "12am".freeze
73
- }
74
-
75
- NUM_SECONDS_IN_DAY = 86400
76
- NUM_SECONDS_IN_HOUR = 3600
77
- NUM_SECONDS_IN_MINUTE = 60
78
-
79
- FORMATS = {
80
- short: "%-l:%M %P".freeze,
81
- medium: "%-l:%M:%S %P".freeze,
82
- time: "%H:%M".freeze
83
- }
84
-
85
- def initialize(h, m=0, s=0)
86
- @hour = Integer(h)
87
- @minute = Integer(m)
88
- @second = Integer(s)
89
-
90
- raise ArgumentError, "hour must be between 0 and 24" unless (0..24).include?(@hour)
91
- if @hour == 24 && (@minute != 0 || @second != 0)
92
- raise ArgumentError, "hour can only be 24 when minute and second are 0"
93
- end
94
- raise ArgumentError, "minute must be between 0 and 59" unless (0..59).include?(@minute)
95
- raise ArgumentError, "second must be between 0 and 59" unless (0..59).include?(@second)
38
+ attr_reader :hour, :minute, :second, :second_of_day
39
+ alias_method :min, :minute
40
+ alias_method :sec, :second
41
+ alias_method :to_i, :second_of_day
42
+
43
+ PARSE_24H_REGEX = /
44
+ \A
45
+ ([01]?\d|2[0-4])
46
+ :?
47
+ ([0-5]\d)?
48
+ :?
49
+ ([0-5]\d)?
50
+ \z
51
+ /x
52
+
53
+ PARSE_12H_REGEX = /
54
+ \A
55
+ (0?\d|1[0-2])
56
+ :?
57
+ ([0-5]\d)?
58
+ :?
59
+ ([0-5]\d)?
60
+ \s*
61
+ ([ap])
62
+ \.?
63
+ \s*
64
+ m?
65
+ \.?
66
+ \z
67
+ /x
68
+
69
+ WORDS = {
70
+ "noon" => "12pm".freeze,
71
+ "midnight" => "12am".freeze
72
+ }
73
+
74
+ NUM_SECONDS_IN_DAY = 86400
75
+ NUM_SECONDS_IN_HOUR = 3600
76
+ NUM_SECONDS_IN_MINUTE = 60
77
+
78
+ FORMATS = {
79
+ short: "%-l:%M %P".freeze,
80
+ medium: "%-l:%M:%S %P".freeze,
81
+ time: "%H:%M".freeze
82
+ }
83
+
84
+ def initialize(h, m=0, s=0)
85
+ @hour = Integer(h)
86
+ @minute = Integer(m)
87
+ @second = Integer(s)
88
+
89
+ raise ArgumentError, "hour must be between 0 and 24" unless (0..24).include?(@hour)
90
+ if @hour == 24 && (@minute != 0 || @second != 0)
91
+ raise ArgumentError, "hour can only be 24 when minute and second are 0"
92
+ end
93
+ raise ArgumentError, "minute must be between 0 and 59" unless (0..59).include?(@minute)
94
+ raise ArgumentError, "second must be between 0 and 59" unless (0..59).include?(@second)
96
95
 
97
- @second_of_day = @hour * 60 * 60 + @minute * 60 + @second
96
+ @second_of_day = @hour * 60 * 60 + @minute * 60 + @second
98
97
 
99
- freeze # TimeOfDay instances are value objects
100
- end
98
+ freeze # TimeOfDay instances are value objects
99
+ end
101
100
 
102
- def <=>(other)
103
- return unless other.respond_to?(:second_of_day)
104
- @second_of_day <=> other.second_of_day
105
- end
101
+ def <=>(other)
102
+ return unless other.respond_to?(:second_of_day)
103
+ @second_of_day <=> other.second_of_day
104
+ end
106
105
 
107
- # Rounding to the given nearest number of seconds
108
- def round(round_sec = 1)
109
- down = self - (self.to_i % round_sec)
110
- up = down + round_sec
106
+ # Rounding to the given nearest number of seconds
107
+ def round(round_sec = 1)
108
+ down = self - (self.to_i % round_sec)
109
+ up = down + round_sec
111
110
 
112
- difference_down = self - down
113
- difference_up = up - self
111
+ difference_down = self - down
112
+ difference_up = up - self
114
113
 
115
- if (difference_down < difference_up)
116
- return down
117
- else
118
- return up
119
- end
114
+ if (difference_down < difference_up)
115
+ return down
116
+ else
117
+ return up
120
118
  end
119
+ end
121
120
 
122
- # Formats identically to Time#strftime
123
- def strftime(format_string)
124
- # Special case 2400 because strftime will load TimeOfDay into Time which
125
- # will convert 24 to 0
126
- format_string = format_string.gsub(/%H|%k/, '24') if @hour == 24
127
- Time.local(2000,1,1, @hour, @minute, @second).strftime(format_string)
128
- end
121
+ # Formats identically to Time#strftime
122
+ def strftime(format_string)
123
+ # Special case 2400 because strftime will load TimeOfDay into Time which
124
+ # will convert 24 to 0
125
+ format_string = format_string.gsub(/%H|%k/, '24') if @hour == 24
126
+ Time.local(2000,1,1, @hour, @minute, @second).strftime(format_string)
127
+ end
129
128
 
130
- def to_formatted_s(format = :default)
131
- if formatter = FORMATS[format]
132
- if formatter.respond_to?(:call)
133
- formatter.call(self).to_s
134
- else
135
- strftime(formatter)
136
- end
129
+ def to_formatted_s(format = :default)
130
+ if formatter = FORMATS[format]
131
+ if formatter.respond_to?(:call)
132
+ formatter.call(self).to_s
137
133
  else
138
- strftime "%H:%M:%S"
134
+ strftime(formatter)
139
135
  end
136
+ else
137
+ strftime "%H:%M:%S"
140
138
  end
141
- alias_method :to_s, :to_formatted_s
142
-
143
- def value_for_database
144
- to_s
145
- end
139
+ end
140
+ alias_method :to_s, :to_formatted_s
146
141
 
147
- # Return a new TimeOfDay num_seconds greater than self. It will wrap around
148
- # at midnight.
149
- def +(num_seconds)
150
- TimeOfDay.from_second_of_day @second_of_day + num_seconds
151
- end
142
+ def value_for_database
143
+ to_s
144
+ end
152
145
 
153
- # Return a new TimeOfDay num_seconds less than self. It will wrap around
154
- # at midnight.
155
- def -(other)
156
- if other.instance_of?(TimeOfDay)
157
- TimeOfDay.from_second_of_day @second_of_day - other.second_of_day
158
- else
159
- TimeOfDay.from_second_of_day @second_of_day - other
160
- end
161
- end
146
+ # Return a new TimeOfDay num_seconds greater than self. It will wrap around
147
+ # at midnight.
148
+ def +(num_seconds)
149
+ TimeOfDay.from_second_of_day @second_of_day + num_seconds
150
+ end
162
151
 
163
- # Returns a Time instance on date using self as the time of day
164
- # Optional time_zone will build time in that zone
165
- def on(date, time_zone=Tod::TimeOfDay.time_zone)
166
- time_zone.local date.year, date.month, date.day, @hour, @minute, @second
152
+ # Return a new TimeOfDay num_seconds less than self. It will wrap around
153
+ # at midnight.
154
+ def -(other)
155
+ if other.instance_of?(TimeOfDay)
156
+ TimeOfDay.from_second_of_day @second_of_day - other.second_of_day
157
+ else
158
+ TimeOfDay.from_second_of_day @second_of_day - other
167
159
  end
160
+ end
168
161
 
169
- # Build a new TimeOfDay instance from second_of_day
170
- #
171
- # TimeOfDay.from_second_of_day(3600) == TimeOfDay.new(1) # => true
172
- def self.from_second_of_day(second_of_day)
173
- second_of_day = Integer(second_of_day)
174
- return new 24 if second_of_day == NUM_SECONDS_IN_DAY
175
- remaining_seconds = second_of_day % NUM_SECONDS_IN_DAY
176
- hour = remaining_seconds / NUM_SECONDS_IN_HOUR
177
- remaining_seconds -= hour * NUM_SECONDS_IN_HOUR
178
- minute = remaining_seconds / NUM_SECONDS_IN_MINUTE
179
- remaining_seconds -= minute * NUM_SECONDS_IN_MINUTE
180
- new hour, minute, remaining_seconds
181
- end
182
- class << self
183
- alias :from_i :from_second_of_day
184
- end
162
+ # Returns a Time instance on date using self as the time of day
163
+ # Optional time_zone will build time in that zone
164
+ def on(date, time_zone=Tod::TimeOfDay.time_zone)
165
+ time_zone.local date.year, date.month, date.day, @hour, @minute, @second
166
+ end
185
167
 
186
- # Build a TimeOfDay instance from string
187
- #
188
- # Strings only need to contain an hour. Minutes, seconds, AM or PM, and colons
189
- # are all optional.
190
- # TimeOfDay.parse "8" # => 08:00:00
191
- # TimeOfDay.parse "8am" # => 08:00:00
192
- # TimeOfDay.parse "8pm" # => 20:00:00
193
- # TimeOfDay.parse "8p" # => 20:00:00
194
- # TimeOfDay.parse "9:30" # => 09:30:00
195
- # TimeOfDay.parse "15:30" # => 15:30:00
196
- # TimeOfDay.parse "3:30pm" # => 15:30:00
197
- # TimeOfDay.parse "1230" # => 12:30:00
198
- # TimeOfDay.parse "3:25:58" # => 03:25:58
199
- # TimeOfDay.parse "515p" # => 17:15:00
200
- # TimeOfDay.parse "151253" # => 15:12:53
201
- # You can give a block, that is called with the input if the string is not parsable.
202
- # If no block is given an ArgumentError is raised if try_parse returns nil.
203
- def self.parse(tod_string)
204
- try_parse(tod_string) || (block_given? ? yield(tod_string) : raise(ArgumentError, "Invalid time of day string"))
205
- end
168
+ # Build a new TimeOfDay instance from second_of_day
169
+ #
170
+ # TimeOfDay.from_second_of_day(3600) == TimeOfDay.new(1) # => true
171
+ def self.from_second_of_day(second_of_day)
172
+ second_of_day = Integer(second_of_day)
173
+ return new 24 if second_of_day == NUM_SECONDS_IN_DAY
174
+ remaining_seconds = second_of_day % NUM_SECONDS_IN_DAY
175
+ hour = remaining_seconds / NUM_SECONDS_IN_HOUR
176
+ remaining_seconds -= hour * NUM_SECONDS_IN_HOUR
177
+ minute = remaining_seconds / NUM_SECONDS_IN_MINUTE
178
+ remaining_seconds -= minute * NUM_SECONDS_IN_MINUTE
179
+ new hour, minute, remaining_seconds
180
+ end
181
+ class << self
182
+ alias :from_i :from_second_of_day
183
+ end
206
184
 
207
- # Same as parse(), but return nil if not parsable (instead of raising an error)
208
- # TimeOfDay.try_parse "8am" # => 08:00:00
209
- # TimeOfDay.try_parse "" # => nil
210
- # TimeOfDay.try_parse "abc" # => nil
211
- def self.try_parse(tod_string)
212
- tod_string = tod_string.to_s
213
- tod_string = tod_string.strip
214
- tod_string = tod_string.downcase
215
- tod_string = WORDS[tod_string] || tod_string
216
- if PARSE_24H_REGEX =~ tod_string || PARSE_12H_REGEX =~ tod_string
217
- hour, minute, second, a_or_p = $1.to_i, $2.to_i, $3.to_i, $4
218
- if hour == 12 && a_or_p == "a"
219
- hour = 0
220
- elsif hour < 12 && a_or_p == "p"
221
- hour += 12
222
- end
185
+ # Build a TimeOfDay instance from string
186
+ #
187
+ # Strings only need to contain an hour. Minutes, seconds, AM or PM, and colons
188
+ # are all optional.
189
+ # TimeOfDay.parse "8" # => 08:00:00
190
+ # TimeOfDay.parse "8am" # => 08:00:00
191
+ # TimeOfDay.parse "8pm" # => 20:00:00
192
+ # TimeOfDay.parse "8p" # => 20:00:00
193
+ # TimeOfDay.parse "9:30" # => 09:30:00
194
+ # TimeOfDay.parse "15:30" # => 15:30:00
195
+ # TimeOfDay.parse "3:30pm" # => 15:30:00
196
+ # TimeOfDay.parse "1230" # => 12:30:00
197
+ # TimeOfDay.parse "3:25:58" # => 03:25:58
198
+ # TimeOfDay.parse "515p" # => 17:15:00
199
+ # TimeOfDay.parse "151253" # => 15:12:53
200
+ # You can give a block, that is called with the input if the string is not parsable.
201
+ # If no block is given an ArgumentError is raised if try_parse returns nil.
202
+ def self.parse(tod_string)
203
+ try_parse(tod_string) || (block_given? ? yield(tod_string) : raise(ArgumentError, "Invalid time of day string"))
204
+ end
223
205
 
224
- new hour, minute, second
225
- else
226
- nil
206
+ # Same as parse(), but return nil if not parsable (instead of raising an error)
207
+ # TimeOfDay.try_parse "8am" # => 08:00:00
208
+ # TimeOfDay.try_parse "" # => nil
209
+ # TimeOfDay.try_parse "abc" # => nil
210
+ def self.try_parse(tod_string)
211
+ tod_string = tod_string.to_s
212
+ tod_string = tod_string.strip
213
+ tod_string = tod_string.downcase
214
+ tod_string = WORDS[tod_string] || tod_string
215
+ if PARSE_24H_REGEX =~ tod_string || PARSE_12H_REGEX =~ tod_string
216
+ hour, minute, second, a_or_p = $1.to_i, $2.to_i, $3.to_i, $4
217
+ if hour == 12 && a_or_p == "a"
218
+ hour = 0
219
+ elsif hour < 12 && a_or_p == "p"
220
+ hour += 12
227
221
  end
228
- end
229
222
 
230
- # Determine if a string is parsable into a TimeOfDay instance
231
- # TimeOfDay.parsable? "8am" # => true
232
- # TimeOfDay.parsable? "abc" # => false
233
- def self.parsable?(tod_string)
234
- !!try_parse(tod_string)
223
+ new hour, minute, second
224
+ else
225
+ nil
235
226
  end
227
+ end
236
228
 
237
- # If ActiveSupport TimeZone is available and set use current time zone else return Time
238
- def self.time_zone
239
- (Time.respond_to?(:zone) && Time.zone) || Time
240
- end
229
+ # Determine if a string is parsable into a TimeOfDay instance
230
+ # TimeOfDay.parsable? "8am" # => true
231
+ # TimeOfDay.parsable? "abc" # => false
232
+ def self.parsable?(tod_string)
233
+ !!try_parse(tod_string)
234
+ end
241
235
 
242
- def self.dump(time_of_day)
243
- time_of_day =
244
- if time_of_day.is_a? Hash
245
- # rails multiparam attribute
246
- # get hour, minute and second and construct new TimeOfDay object
247
- ::Tod::TimeOfDay.new(time_of_day[4], time_of_day[5], time_of_day[6])
248
- else
249
- # return nil, if input is not parsable
250
- Tod::TimeOfDay(time_of_day){}
251
- end
252
- time_of_day.to_s if time_of_day
253
- end
236
+ # If ActiveSupport TimeZone is available and set use current time zone else return Time
237
+ def self.time_zone
238
+ (Time.respond_to?(:zone) && Time.zone) || Time
239
+ end
254
240
 
255
- def self.load(time)
256
- if time && !time.to_s.empty?
257
- return ::Tod::TimeOfDay.new(24) if time.respond_to?(:day) && time.day == 2 && time.hour == 0 && time.min == 0 && time.sec == 0
258
- ::Tod::TimeOfDay(time)
259
- end
241
+ def self.dump(time_of_day)
242
+ time_of_day =
243
+ if time_of_day.is_a? Hash
244
+ # rails multiparam attribute
245
+ # get hour, minute and second and construct new TimeOfDay object
246
+ ::Tod::TimeOfDay.new(time_of_day[4], time_of_day[5], time_of_day[6])
247
+ else
248
+ # return nil, if input is not parsable
249
+ Tod::TimeOfDay(time_of_day){}
250
+ end
251
+ time_of_day.to_s if time_of_day
252
+ end
253
+
254
+ def self.load(time)
255
+ if time && !time.to_s.empty?
256
+ return ::Tod::TimeOfDay.new(24) if time.respond_to?(:day) && time.day == 2 && time.hour == 0 && time.min == 0 && time.sec == 0
257
+ ::Tod::TimeOfDay(time)
260
258
  end
261
259
  end
262
260
  end