Skip to content

Commit bb4a3c1

Browse files
Fix time-only DateTime.parse under freeze (#440)
* Fix time-only DateTime.parse under freeze DateTime.parse('HH:MM') previously fell back to parsed_date + travel_offset_days, with travel_offset_days = (@travel_offset / 86400).round. Because @travel_offset measures the gap between the frozen moment and the real system clock, that rounding stepped up or down depending on how close the real clock was to a 12‑hour boundary. For example, freezing at 2017-08-10 10:00 UTC while the host clock is 2025-11-13 22:00 UTC yields an offset of N.5 days, so rounding adds an extra day and parsing “01:00” returns 2017-08-09 instead of 2017-08-10. Anchor hour/minute-only parses to the mocked year/month/day and add deterministic regression tests to ensure time-only input no longer depends on the host clock. * Rename tests for DateTime.parse HH:MM format - test_date_time_parse_hhmm_uses_frozen_date_not_real_clock: regression test ensuring parsed time uses frozen date, not host clock - test_date_time_parse_hhmm_format_returns_correct_time: basic HH:MM format parsing * update test according to the PR comments konieczkow made --------- Co-authored-by: Josh Cronemeyer <joshuacronemeyer@gmail.com>
1 parent e4bba8c commit bb4a3c1

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

lib/timecop/time_extensions.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ def parse_with_mock_date(*args)
154154
Date.closest_wday(date_hash[:wday]).to_datetime
155155
when date_hash[:hour] && date_hash[:min] && date_hash[:sec]
156156
DateTime.new(mocked_time_stack_item.year, mocked_time_stack_item.month, mocked_time_stack_item.day, date_hash[:hour], date_hash[:min], date_hash[:sec])
157+
when date_hash[:hour] && date_hash[:min]
158+
DateTime.new(mocked_time_stack_item.year, mocked_time_stack_item.month, mocked_time_stack_item.day, date_hash[:hour], date_hash[:min], 0)
157159
else
158160
parsed_date + mocked_time_stack_item.travel_offset_days
159161
end

test/date_time_parse_scenarios.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,24 @@ def test_date_time_parse_time_only_scenario
6464
assert_equal DateTime.parse("2008-09-01T15:00:00"), DateTime.parse('15:00:00')
6565
end
6666

67+
def test_date_time_parse_hhmm_uses_frozen_date_not_real_clock
68+
real_now = Time.now_without_mock_time.utc
69+
offset = 12 * 3600 + 30
70+
freeze_time = real_now.hour >= 12 ? real_now - offset : real_now + offset
71+
72+
Timecop.freeze(freeze_time) do
73+
expected = DateTime.new(freeze_time.year, freeze_time.month, freeze_time.day, 1, 0, 0, 0)
74+
assert_equal expected, DateTime.parse('01:00')
75+
end
76+
end
77+
78+
def test_date_time_parse_hhmm_format_returns_correct_time
79+
assert_equal DateTime.new(2008, 9, 1, 0, 0, 0), DateTime.parse('00:00')
80+
assert_equal DateTime.new(2008, 9, 1, 1, 0, 0), DateTime.parse('01:00')
81+
assert_equal DateTime.new(2008, 9, 1, 12, 30, 0), DateTime.parse('12:30')
82+
assert_equal DateTime.new(2008, 9, 1, 23, 59, 0), DateTime.parse('23:59')
83+
end
84+
6785
def test_date_time_parse_month_year
6886
assert_equal DateTime.parse("2012-12-01"), DateTime.parse('DEC 2012')
6987
end

0 commit comments

Comments
 (0)