timecop icon indicating copy to clipboard operation
timecop copied to clipboard

Stubbing out parse and strptime on Date and DateTime is incomplete and inconsistent

Open joshuacronemeyer opened this issue 5 years ago • 4 comments
trafficstars

I've noticed that there are a handful of bugs and pull requests around Timecop stubbing out parse and strptime. There are also quite a few historical bugs, so it's been a source of problems for a long time now.

Open bugs include: https://github.com/travisjeffery/timecop/issues/261, https://github.com/travisjeffery/timecop/issues/240, https://github.com/travisjeffery/timecop/issues/222

Pulls include: https://github.com/travisjeffery/timecop/pull/250, https://github.com/travisjeffery/timecop/pull/262, https://github.com/travisjeffery/timecop/pull/121

None of the pulls really address all the issues, just very specific edge cases. The intent of patching these methods is so that when ruby converts a date string that requires making an inference based on the current time it can use timecop's frozen time. Unfortunately the patched code doesn't handle things like commercial dates (:cwyear, :cweek) When I saw that I figured there are probably other unhandled cases. Sure enough I quickly found another

julian = "14125"
Date.strptime(julian, "%y%j").to_s
 => "2014-05-05"
Timecop.freeze(2016, 10, 16, 10, 0, 0)
Date.strptime(julian, "%y%j").to_s
 => "2014-10-16"

which happens because we don't handle :yday coming back from Date._strptime. Maybe there are more.

I'm interested if there was any debate as to if timecop should support stubbing date string parsing. Seems like it all started with this PR https://github.com/travisjeffery/timecop/issues/108 and we've just made this an implicit feature that continues to get fleshed out 1 edge case at a time.

Maybe worth a shot to put together a comprehensive set of tests for dates in different formats, and apply them to all the parts of the code that stub parsing date strings Date#strptime, Date#parse

I'd be up for it, but it looks like there are no active maintainers for the Gem. I'm watching https://github.com/travisjeffery/timecop/issues/256 and i'll circle back on this when that gets resolved.

joshuacronemeyer avatar Oct 05 '20 19:10 joshuacronemeyer

@joshuacronemeyer do you want to be a maintainer?

travisjeffery avatar Oct 13 '20 04:10 travisjeffery

Ok. Yes @travisjeffery i'm happy to help out.

joshuacronemeyer avatar Oct 13 '20 17:10 joshuacronemeyer

I was researching the new pull request https://github.com/travisjeffery/timecop/pull/266 which fixes another behavior with our implementation of Date::strptime. When Ruby Date infers a day or month from a string they infer the first day or month, but our implementation infers the day or month from the mocked time or current time. So in addition to the bug raised there we've got another related issue where Date.strptime('1999', '%Y') doesn't return the same result after you require Timecop.

joshuacronemeyer avatar Oct 15 '20 20:10 joshuacronemeyer

Earlier I raised the question of if Timecop should even be monkeying with these methods. My thinking on this issue is that the community has already decided there is value to having strptime, parse, etc. aware of mocked time, and we just need to continue working on our implementation to make it a good one. We'll keep chipping away at that.

joshuacronemeyer avatar Oct 15 '20 20:10 joshuacronemeyer

closing for lack of activity

joshuacronemeyer avatar Aug 06 '23 20:08 joshuacronemeyer

I have witnessed this issue. Has it been addressed?

dsmontoya avatar Aug 21 '23 20:08 dsmontoya

We have added support for quite a few less common date formats in the most recent release. If you have scenarios that are not working correctly on the newest release please file a ticket. At the end of the day we're going to continue to support these use cases.

If you're talking about the julian date scenario mentioned here this particular one is fixed.

joshuacronemeyer avatar Aug 21 '23 21:08 joshuacronemeyer

This particular date is being parsed to Tue, 04 Oct 2022 09:00:00 +0000 when the code is executed after 18:59 (-0600) in my computer:

Timecop.freeze(Time.parse('2022-10-05 8:00:00')) do
  DateTime.parse('09:00:00')
end

dsmontoya avatar Aug 21 '23 23:08 dsmontoya