|
class << (active_model = Object.new) # Simplified ActiveModel version
|
|
def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil)
|
|
time = ::Time.utc(year, mon, mday, hour, min, sec, microsec) rescue return
|
|
if offset
|
|
time = time.getlocal(offset)
|
|
time -= time.utc_offset
|
|
end
|
|
time
|
|
end
|
|
|
|
ISO_DATETIME = /
|
|
\A
|
|
(\d{4})-(\d\d)-(\d\d)(?:T|\s) # 2020-06-20T
|
|
(\d\d):(\d\d):(\d\d)(?:\.(\d{1,6}+)\d*)? # 10:20:30.123456
|
|
(Z|[+-]\d\d(?::?\d\d)?)? # +09:00
|
|
\z
|
|
/x
|
|
|
|
def fast_string_to_time(string)
|
|
return unless ISO_DATETIME =~ string
|
|
|
|
if usec = $7
|
|
usec_len = usec.length
|
|
usec = usec.to_i
|
|
if usec_len < 6
|
|
usec *= 10**(6 - usec_len)
|
|
end
|
|
end
|
|
|
|
offset = $8
|
|
|
|
new_time($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, usec, offset)
|
|
end
|
|
end
|
|
|
|
class << (time = Object.new)
|
|
def string_to_time(string)
|
|
::Time.new(string) unless Integer(string, exception: false)
|
|
end
|
|
end
|
|
|
|
require 'benchmark/ips'
|
|
|
|
t = "2020-06-20T10:20:30.123456+09:00"
|
|
# p active_model.fast_string_to_time(t)
|
|
# p time.string_to_time(t)
|
|
Benchmark.ips do |x|
|
|
x.report("active_model") {active_model.fast_string_to_time(t)}
|
|
x.report("time") {time.string_to_time(t)}
|
|
end
|