Sometimes you have a Time or DateTime object in Ruby and you want to zero out the milliseconds, seconds, minutes, or hours. And if you’re zeroing out a larger element like minutes, you’d like it to automatically zero out the smaller elements like seconds and milliseconds too.
It turns out ActiveSupport extends Time and DateTime with a method to do this: change. As the documentation says, “The time options (hour, minute, sec, usec) reset cascadingly, so if only the hour is passed, then minute, sec, and usec is set to 0. If the hour and minute is passed, then sec and usec is set to 0.”
To truncate a Time to the second, minute, hour, or day:
time.change(:usec => 0) # zero out milliseconds time.change(:sec => 0) # zero out seconds, milliseconds time.change(:min => 0) # zero out mins, secs, & usecs time.change(:hour => 0) # zero out hrs, mins, secs, usecs
To truncate a DateTime to the minute, hour, or day:
datetime.change(:sec => 0) # zero out seconds datetime.change(:min => 0) # zero out mins and secs datetime.change(:hour => 0) # zero out hrs, mins, secs
Sensibly, changing the year, month, or day of a DateTime does not reset the lower elements to zero.
ActiveSupport also adds the change method to Date, but since the only elements are year, month, and day, it never zeroes out the smaller elements when you set a larger element.