New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Timecop.freeze with Dates is lossy and users should be warned #100
Comments
You could have demonstrated this bug more concisely as: Timecop.freeze('2013-04-24'.to_date) { Date.today }
Tue, 23 Apr 2013
This comment makes no sense to me. Offset is irrelevant for the purposes of a date. |
@BrokenLadder because of the interplay of > Time.now.utc_offset # ENV['TZ'] is nil, but computer's clock is UTC.
# => 0
> Time.zone = -2 # manually set Time.zone to negative offset. 2 bypasses AS's DST issues
# => -2
> Timecop.freeze('2013-04-24'.to_date) { Date.today }
# => Wed, 24 Apr 2013
> Time.zone = 2 # manually set Time.zone to positive offset. 2 bypasses AS's DST issues
# => 2
> Timecop.freeze('2013-04-24'.to_date) { Date.today }
# => Tue, 23 Apr 2013 My point though, was not just that there is a bug, but that the assumptions inherent in making the conversion from
A date is defined as the period between a midnight and the following midnight, so moment-in-time data (such as the timestamp at the beginning of that day) cannot be extracted without additional information or assumptions about the UTC-offset; it is, therefore a lossy representation of time. Timecop is built to freeze the time, not the date, and using |
I would certainly agree that you can't convert a Date to a Time, at least without supplying a time zone to whatever function does the conversion. Your argument that a Date is "lossy" could applied to any time. E.g. a time that is accurate down to the millesecond can only approximate a time in nanoseconds. |
@BrokenLadder this is not an issue of precision; if it were, a round-trip from least-precise representation ( In our case above, the assumptions inherent in that first conversion (which are simple without |
Your previous comment was about precision:
A UTC offset in this example is effectively a "less significant digit". Trying to get the time that starts a Date when you don't know the time zone is exactly like trying to get the minute of the current hour when you only have value of the hour hand. Mathematically speaking, your comment is absolutely about precision. |
@BrokenLadder an offset is a shift applied to a "less significant digit" (the hours, or more correctly the minutes), which has an effect different than that of just a less significant digit in that it can "overflow" into the part of the value we care about. But let's stop arguing over that, since we seem to agree on the main point; I'll bring it back to what you said earlier:
This is the point, this is the whole reason why this feature should be deprecated. The function that does the conversion in |
But how does this require any more assumptions than, say, '2013-04-20'? |
@BrokenLadder that assumption is just in another place:
|
Timecop.freeze('2013-04-24'.to_date) { Date.today }
=> Tue, 23 Apr 2013
Timecop.freeze('2013-04-24') { Date.today }
=> Wed, 24 Apr 2013 |
The first example you gave does not go through Timecop.freeze('2013-04-24'.to_date) { Date.today }
#=> Tue, 23 Apr 2013 In the second example (which does go through Timecop.freeze('2013-04-24') { Date.today }
=> Wed, 24 Apr 2013 |
@yaauie any updates on this issue? |
I'm not a maintainer on this project, and @travisjeffery hasn't chimed in. At this point you can assume that it is a Bad Idea and should freeze to something that cleanly and unambiguously resolves to a Time, knowing also that the interplay between |
This is a pretty big caveat that definitely bit me in the arse today, +1 to getting this fixed. |
I just ran into this issue and it cost me a bundle of time. Definitely worth fixing. I worked around the issue for myself by simply calling to_time on the date argument. |
👍 to_time fixes the issue, but investigation takes some time :/ |
A workaround: |
Related issue? => AdminGlobalSetting.interviews_date #=> 2016-06-12 db_column is just date
date = AdminGlobalSetting.interviews_date - 1.day
puts date #=> 2016-06-11
Timecop.freeze(date) do
puts Date.today #=> 2016-06-10
DateChecker.new.perform
end I'm passing in the 11th and its freezing the 10th? Update date #=> 2016-06-11
Timecop.freeze(date) do
Date.today #=> 2016-06-10
Date.current #=> 2016-06-11
DateChecker.new.perform
end |
When running the tests locally, I had two tests fail due to an issue with Timecop. A similar issue has been opened on Timecop's repo, but it has not been addressed: travisjeffery/timecop#100 It seems that using a string in Timecop.freeze fixes this issue. This pull request is opened for conversation and direction on the best way to resolve the issue.
@yaauie Great catch. This issue saved me some time. |
Realistically, ActiveSupport's
Time.zone
being set andTimecop.freeze
-ing withDate
objects are not compatible.Date
is a lossy representation ofTime
in Ruby anyway since it doesn't store offset, and the assumptions we make to handle that are surprising.I think that freezing to
Date
objects should be deprecated.Consider the following:
The text was updated successfully, but these errors were encountered: