Dank euch beiden . Da ich Rails nicht verwende, habe ich den Code kopiert, um einen Leistungsbenchmark zu erstellen.
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]
# Correctness check.
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
Hier sind die Ergebnisse:
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)
Scheint wie meine erste Abschneide Version noch am effizientesten ist, mit Ausnahme des Jahres Fall. Es gibt eine kleine Eigenart im Jahr für truncate
und truncate3
obwohl. Es wird angezeigt, wie
2008-12-31 23:00:00 -0800
statt
2009-01-01 00:00:00 -0700
Irgendwelche Ideen, warum?
Das Problem mit dem Jahr Fall zu verwenden, kann die Zeit sein. local mit 10 args ist überspezifiziert, und ich bin mir nicht sicher, wie die Zeitbibliothek mit Konflikten umgeht: YDAY, WDAY sind redundant und isDst kann mit "PDT" vs "PST" nicht synchron sein. Eine Möglichkeit, den Fehler loszuwerden, ist 'Time.local t.reverse [4,6]' – AShelly
Diese Antwort ist genau das, wonach ich gesucht habe. Vielen Dank. Ich habe 'Time.local (* t)' auf 'self.class.gm (* t)' um UTC zu verwenden und wenn es eine Unterklasse von 'Time' ist, wird es seine eigene Klasse benutzen. – animatedgif