Skip to content

Commit

Permalink
Calculate travel_offset to align with the precision of argument to Ti…
Browse files Browse the repository at this point in the history
…mecop.travel (#421)

* Calculate travel_offset to align with clock precision

Subtracting two `Time`s returns a `Float`, which may not be accurate
down to subsecond resolution. Because `Float`s are stored as double-
precision values (IEEE 754), they can have resolutions much higher than
the typical minimum clock precision of 10e-9 seconds. Which can result
in two `Time` object not comparing as equal when they are the same down
to the nanosecond, when one has had a travel_offset applied to it.

* Use the realtime clock's resolution when testing travel_offset's alignment

* Improve failure message for travel_offset alignment test

* Test that time_offset keeps precision of very high times passed to Timecop.travel

* Mention this change in History.md
  • Loading branch information
dgholz authored Aug 14, 2024
1 parent e556094 commit e05c2c0
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 1 deletion.
2 changes: 2 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- Calculate travel_offset to align with the precision of argument to Timecop.travel ([#421](https://github.com/travisjeffery/timecop/pull/421))

## v0.9.10

- Make Process.clock_gettime configurable and turned off by default (for backwards compatability) ([#427](https://github.com/travisjeffery/timecop/pull/427))
Expand Down
2 changes: 1 addition & 1 deletion lib/timecop/time_stack_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def parse_time(*args)
end

def compute_travel_offset
time - Time.now_without_mock_time
time.to_r - Time.now_without_mock_time.to_r
end

def times_are_equal_within_epsilon t1, t2, epsilon_in_seconds
Expand Down
18 changes: 18 additions & 0 deletions test/time_stack_item_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,22 @@ def test_datetime_timezones
assert_equal dt, now, "#{dt.to_f}, #{now.to_f}"
end
end

def test_travel_offset_aligns_to_clock
t = Time.now
stack_item = Timecop::TimeStackItem.new(:travel, t)
travel_offset_denom = stack_item.travel_offset.to_r.denominator
clock_resolution = Process.clock_getres(:CLOCK_REALTIME, :hertz)
assert_equal 0, clock_resolution.modulo(travel_offset_denom),
"travel offset precision (#{travel_offset_denom}) does not align with clock resolution (#{clock_resolution})"
end

def test_travel_offset_aligns_to_travel_time
t = Time.now + 0.001_002_003_004
stack_item = Timecop::TimeStackItem.new(:travel, t)
travel_offset_denom = stack_item.travel_offset.to_r.denominator
travel_time_denom = t.to_r.denominator
assert_equal 0, travel_time_denom.modulo(travel_offset_denom),
"travel offset precision (#{travel_offset_denom}) does not align with travel time precision (#{travel_time_denom})"
end
end

0 comments on commit e05c2c0

Please sign in to comment.