Skip to content

Time.now sometimes has greater-than-nanosecond precision when called under Timecop.travel #420

@dgholz

Description

@dgholz

Hello, I have a test that looks like:

Timecop.travel(some_date)
company = create_company
[…]
Timecop.freeze
EmailPolicy::Actions::Block(company)
expect(Preferences::EmailRateLimit.for(company).blocked_until).to eq(6.hours.from_now)

Where EmailPolicy::Actions::Block calls Time.now, and serialised the date to interact with other systems, and Preferences::EmailRateLimit deserialised the date. Times are serialised down to the nanosecond.

It failed with:

       Failure/Error: expect(Preferences::EmailRateLimit.for(company).blocked_until).to eq(6.hours.from_now)
  
         expected: 2024-05-14 19:42:47.696001634 +0000
              got: 2024-05-14 19:42:47.696001634 +0000

Which baffled me a bit, since I didn't consider that the Time used to calculate 6.hours.from_now would have a fraction of a nanosecond difference to the deserialised Time from the Preferences system.

Previously, the test only had the Timecop.freeze line & worked great. It was only after adding the Timecop.travel that the two identical-looking Times started comparing as unequal. So that made me look at how the travel_offset was added to create the Time.now used for Timecop.freeze, and I saw it was a Float with a much higher precision than was possible with a computer clock.

I have some ideas on how to change my test to pass, but thought I'd raise this issue to highlight that the Times returned under Timecop.travel may sometimes have more precision than you might expect, and shouldn't be compared to Times created from other sources.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions