I need to round a DateTime
and also a Time
to the nearest 15 minute interval. My thought is to zero out the seconds and the milliseconds (do those exist in a DateTime
or Time
?) and maybe even nanoseconds? And then divide the number of minutes by 15, round that, then multiply the result by 15 and set that to be the minutes:
# zero out the seconds
time -= time.sec.seconds
# zero out the milliseconds (does that exist?)
# zero out the nanoseconds (less likely this exists)
minutes_should_be = (time.min / 15.to_f).round * 15
time += (minutes_should_be - time.min).minutes
So I guess my question is if there is a better way to do this and if milliseconds and nanoseconds exist in a DateTime
or Time
? There is a nsec method for nanoseconds, but I think that's the total nanoseconds since epoch.
The following should do the trick:
##
# rounds a Time or DateTime to the neares 15 minutes
def round_to_15_minutes(t)
rounded = Time.at((t.to_time.to_i / 900.0).round * 900)
t.is_a?(DateTime) ? rounded.to_datetime : rounded
end
The function converts the input to a Time
object, which can be converted to the seconds since the epoch with to_i
(this automatically strips nano-/milliseconds). Then we divide by 15 minutes (900 seconds) and round the resulting float. This automatically rounds the time to the nearest 15 minutes. Now, we just need to multiply the result by 15 minutes and convert it to a (date)time again.
round_to_15_minutes Time.new(2013, 9, 13, 0, 7, 0, "+02:00")
#=> 2013-09-13 00:00:00 +0200
round_to_15_minutes Time.new(2013, 9, 13, 0, 8, 0, "+02:00")
#=> 2013-09-13 00:15:00 +0200
round_to_15_minutes Time.new(2013, 9, 13, 0, 22, 29, "+02:00")
#=> 2013-09-13 00:15:00 +0200
round_to_15_minutes Time.new(2013, 9, 13, 0, 22, 30, "+02:00")
#=> 2013-09-13 00:30:00 +0200
round_to_15_minutes DateTime.now
#=> #<DateTime: 2013-09-13T01:00:00+02:00 ((2456548j,82800s,0n),+7200s,2299161j)>
A generic rounding solution for DateTime, based on Tessi's answer:
class DateTime
def round(granularity=1.hour)
Time.at((self.to_time.to_i/granularity).round * granularity).to_datetime
end
end
Example usage:
DateTime.now.round 15.minutes
> Fri, 15 May 2015 11:15:00 +0100
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With