Skip to content

Timecop freeze makes DateTime.parse('HH:MM') jump to the wrong day #441

@konieczkow

Description

@konieczkow

Hey everyone, I was chasing down some flaky tests related to time parsing and wanted to share what I found. Let me know if I’m misunderstanding anything. Here’s the behavior I observed and the PR that came out of it.

I noticed that when Timecop freezes time and you parse a string that only contains hours and minutes (e.g., "01:00"), the resulting DateTime can depend on the host clock instead of the frozen date. The fallback path in DateTime.parse_with_mock_date uses:

travel_offset_days = (@travel_offset / 86400).round

Since @travel_offset is the difference between the frozen moment and the real system time, things get unstable when that difference is roughly +/-12 hours from a whole number of days. In those cases, the rounding flips and the parsed DateTime lands a full day earlier or later.

Example:

Timecop.freeze(Time.utc(2017, 8, 10, 10, 0, 0))
# Host clock is 2025-11-13 22:00 UTC

DateTime.parse("01:00")
# => Wed, 09 Aug 2017 01:00:00 +0000 (one day too early)

But if the host clock is just one hour earlier (21:00 UTC):

# => Thu, 10 Aug 2017 01:00:00 +0000

This reproduces cleanly using faketime:

faketime '2025-11-13 22:00:00' bundle exec rails c
Timecop.freeze(Time.utc(2017, 8, 10, 10, 0, 0))
DateTime.parse("01:00") # => 2017-08-09 01:00:00

So tests that rely on parsing time-only strings can become flaky depending on what time of day the host is at.

Proposed fix / PR

#440

Happy to adjust if I’ve misunderstood how this path is meant to behave.

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