Skip to content

Commit 9f6e82e

Browse files
author
David Heinemeier Hansson
committed
Fix rounding errors with #travel_to by resetting the usec on any passed time to zero, so we only travel with per-second precision, not anything deeper than that.
1 parent 88d27ae commit 9f6e82e

File tree

3 files changed

+20
-4
lines changed

3 files changed

+20
-4
lines changed

activesupport/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
* Fix rounding errors with #travel_to by resetting the usec on any passed time to zero, so we only travel
2+
with per-second precision, not anything deeper than that.
3+
4+
*DHH*
5+
16
* Fix ActiveSupport::TestCase not to order users' test cases by default.
27
If this change breaks your tests because your tests are order dependent, you need to explicitly call
38
ActiveSupport::TestCase.my_tests_are_order_dependent! at the top of your tests.

activesupport/lib/active_support/testing/time_helpers.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ def travel(duration, &block)
7878
# or <tt>Date.today</tt>, in order to honor the application time zone
7979
# please always use <tt>Time.current</tt> and <tt>Date.current</tt>.)
8080
#
81+
# Note that the usec for the time passed will be set to 0 to prevent rounding
82+
# errors with external services, like MySQL (which will round instead of floor,
83+
# leading to off-by-one-second errors).
84+
#
8185
# This method also accepts a block, which will return the current time back to its original
8286
# state at the end of the block:
8387
#
@@ -90,7 +94,7 @@ def travel_to(date_or_time, &block)
9094
if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
9195
now = date_or_time.midnight.to_time
9296
else
93-
now = date_or_time.to_time
97+
now = date_or_time.to_time.change(usec: 0)
9498
end
9599

96100
simple_stubs.stub_object(Time, :now, now)

activesupport/test/test_test.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,19 @@ def test_time_helper_travel
188188
expected_time = Time.now + 1.day
189189
travel 1.day
190190

191-
assert_equal expected_time, Time.now
191+
assert_equal expected_time.to_s(:db), Time.now.to_s(:db)
192192
assert_equal expected_time.to_date, Date.today
193193
end
194194

195195
def test_time_helper_travel_with_block
196196
expected_time = Time.now + 1.day
197197

198198
travel 1.day do
199-
assert_equal expected_time, Time.now
199+
assert_equal expected_time.to_s(:db), Time.now.to_s(:db)
200200
assert_equal expected_time.to_date, Date.today
201201
end
202202

203-
assert_not_equal expected_time, Time.now
203+
assert_not_equal expected_time.to_s(:db), Time.now.to_s(:db)
204204
assert_not_equal expected_time.to_date, Date.today
205205
end
206206

@@ -235,4 +235,11 @@ def test_time_helper_travel_back
235235
assert_not_equal expected_time, Time.now
236236
assert_not_equal Date.new(2004, 11, 24), Date.today
237237
end
238+
239+
def test_travel_to_will_reset_the_usec_to_avoid_mysql_rouding
240+
travel_to Time.utc(2014, 10, 10, 10, 10, 50, 999999) do
241+
assert_equal 50, Time.now.sec
242+
assert_equal 0, Time.now.usec
243+
end
244+
end
238245
end

0 commit comments

Comments
 (0)