Thanks to both of you. Since I do not use Rails, I copied the code to run a performance test.
require 'benchmark'
class Time
def truncate resolution
t = to_a
case resolution
when :min
t[0] = 0
when :hour
t[0] = t[1] = 0
when :day
t[0] = t[1] = t[2] = 0
when :week
t[0] = t[1] = t[2] = 0
t[3] -= t[6] - 1
when :month
t[0] = t[1] = t[2] = 0
t[3] = 1
when :year
t[0] = t[1] = t[2] = 0
t[3] = t[4] = 1
end
Time.local *t
end
def truncate2 resolution
opts = {}
case resolution
when :min
opts[:sec] = 0
when :hour
opts[:sec] = opts[:min] = 0
when :day
opts[:sec] = opts[:min] = opts[:hour] = 0
when :week
opts[:sec] = opts[:min] = opts[:hour] = 0
opts[:day] = wday - 1 if wday != 1
when :month
opts[:sec] = opts[:min] = opts[:hour] = 0
opts[:day] = 1
when :year
opts[:sec] = opts[:min] = opts[:hour] = 0
opts[:day] = opts[:month] = 1
end
change opts
end
def truncate3 resolution
t = to_a
if resolution == :week
t[0] = t[1] = 0
t[2] = 1
t[3] -= t[6] - 1
else
len = [:sec, :min, :hour, :day, :month, :year].index(resolution)
t.fill(0, 0, len)
t.fill(1, 3, len-3)
end
Time.local *t
end
def change opts
Time.local(
opts[:year] || year,
opts[:month] || month,
opts[:day] || day,
opts[:hour] || hour,
opts[:min] || (opts[:hour] ? 0 : min),
opts[:sec] || ((opts[:hour] || opts[:min]) ? 0 : sec),
)
end
end
Resolutions = [:sec, :min, :hour, :day, :week, :month, :year]
puts Resolutions.map { |r| "#{r}: #{Time.now.truncate r}" } << "\n"
puts Resolutions.map { |r| "#{r}: #{Time.now.truncate2 r}" } << "\n"
puts Resolutions.map { |r| "#{r}: #{Time.now.truncate3 r}" } << "\n"
n = 100000
now = Time.now
Benchmark.bm(10) do |x|
x.report("truncate") { n.times { Resolutions.each { |r| now.truncate r } } }
x.report("truncate2") { n.times { Resolutions.each { |r| now.truncate2 r } } }
x.report("truncate3") { n.times { Resolutions.each { |r| now.truncate3 r } } }
end
Benchmark.bm(10) do |x|
Resolutions.each do |unit|
x.report("#{unit}") { n.times { now.truncate unit } }
x.report("#{unit}2") { n.times { now.truncate2 unit } }
x.report("#{unit}3") { n.times { now.truncate3 unit } }
end
end
Here are the results:
sec: 2009-05-26 13:44:20 -0700
min: 2009-05-26 13:44:00 -0700
hour: 2009-05-26 13:00:00 -0700
day: 2009-05-26 00:00:00 -0700
week: 2009-05-25 00:00:00 -0700
month: 2009-05-01 00:00:00 -0700
year: 2008-12-31 23:00:00 -0800
sec: 2009-05-26 13:44:20 -0700
min: 2009-05-26 13:44:00 -0700
hour: 2009-05-26 13:00:00 -0700
day: 2009-05-26 00:00:00 -0700
week: 2009-05-01 00:00:00 -0700
month: 2009-05-01 00:00:00 -0700
year: 2009-01-01 00:00:00 -0800
sec: 2009-05-26 13:44:20 -0700
min: 2009-05-26 13:44:00 -0700
hour: 2009-05-26 13:00:00 -0700
day: 2009-05-26 00:00:00 -0700
week: 2009-05-25 01:00:00 -0700
month: 2009-05-01 00:00:00 -0700
year: 2008-12-31 23:00:00 -0800
user system total real
truncate 5.910000 0.020000 5.930000 ( 5.947453)
truncate2 6.180000 0.020000 6.200000 ( 6.232918)
truncate3 6.150000 0.020000 6.170000 ( 6.253931)
user system total real
sec 0.720000 0.000000 0.720000 ( 0.749040)
sec2 0.830000 0.010000 0.840000 ( 0.863029)
sec3 0.800000 0.000000 0.800000 ( 0.820477)
min 0.700000 0.000000 0.700000 ( 0.709238)
min2 0.860000 0.010000 0.870000 ( 0.860168)
min3 0.770000 0.000000 0.770000 ( 0.795734)
hour 0.680000 0.000000 0.680000 ( 0.705306)
hour2 0.850000 0.010000 0.860000 ( 0.867235)
hour3 0.740000 0.000000 0.740000 ( 0.746338)
day 0.720000 0.000000 0.720000 ( 0.724324)
day2 0.890000 0.010000 0.900000 ( 0.894312)
day3 0.780000 0.000000 0.780000 ( 0.788007)
week 0.730000 0.000000 0.730000 ( 0.736604)
week2 0.910000 0.000000 0.910000 ( 0.910925)
week3 0.600000 0.000000 0.600000 ( 0.611683)
month 0.720000 0.000000 0.720000 ( 0.719515)
month2 0.880000 0.010000 0.890000 ( 0.888045)
month3 0.780000 0.000000 0.780000 ( 0.789726)
year 1.540000 0.010000 1.550000 ( 1.565335)
year2 0.830000 0.000000 0.830000 ( 0.849737)
year3 1.600000 0.010000 1.610000 ( 1.644958)
It seems that my first version of truncation is still the most effective, except for the case of the year. There is little fad for truncateand this year truncate3. It is displayed as
2008-12-31 23:00:00 -0800
but not
2009-01-01 00:00:00 -0700
Any ideas why?
mavam source
share