Skip to content

Fix datetime accuracy - #9679

Merged
mhvk merged 4 commits into
astropy:masterfrom
aarchiba:datetime-accuracy
Nov 27, 2019
Merged

mhvk merged 4 commits into
astropy:masterfrom
aarchiba:datetime-accuracy

Conversation

@aarchiba

Copy link
Copy Markdown
Contributor

Fixes #9579

Description

This pull request is to address accuracy limitations in datetime <-> Time conversion revealed by PR #9532 and reported in bug #9579 .

Fixes #9579

@astropy-bot astropy-bot Bot added the time label Nov 25, 2019
@pllim pllim added this to the v4.0.1 milestone Nov 25, 2019
@pllim pllim added the Bug label Nov 25, 2019
@pllim
pllim requested review from mhvk and taldcroft November 25, 2019 22:24
@aarchiba

Copy link
Copy Markdown
Contributor Author

Work on #9532 suggests that this does not completely fix the problem; I don't yet know why, but TimeDelta -> datetime.timedelta -> TimeDelta slips about ten microseconds. The other roundtrip appears to be fine, somehow? I'll update here when I've sorted it.

@aarchiba

Copy link
Copy Markdown
Contributor Author

Work on #9532 suggests that this does not completely fix the problem; I don't yet know why, but TimeDelta -> datetime.timedelta -> TimeDelta slips about ten microseconds. The other roundtrip appears to be fine, somehow? I'll update here when I've sorted it.

No actually it's fine, I had accidentally converted through a Time default format's .value method, which throws away accuracy.

@aarchiba

Copy link
Copy Markdown
Contributor Author

I guess if it isn't going into 4.0 it needs a changelog entry?

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Small comments only.

Maybe post here an example where this fails; I'd quite happily merge this unless there is a real show-stopper, as it would seem to give good improvements already.

Comment thread astropy/time/formats.py Outdated
for jd, out in iterator:
out[...] = datetime.timedelta(days=jd.item())
for jd1, jd2, out in iterator:
jd1_, jd2_ = day_frac(jd1.item(), jd2.item())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .item() shouldn't be necessary here. Also, would think that the day_frac is not needed either, since timedelta would do it internally (but haven't tested).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing code used .item() but I don't know why, so I left it.

Didn't we have this discussion, that astropy does not guarantee anything about the values of jd1 and jd2? Specifically, custom formats pass through no checking, and only some code will break when presented with unusual values here. Scale conversion could also produce non-compliant jd1 and jd2, though I think the fix for that was merged. My argument was that having a near-invariant was worse than not providing any invariant, because code would depend on it, as your suggestion does, and then some obscure bits of code would break, in this case in subtle ways.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we had. My suggestion was simply to check whether timedelta does the rounding for one and thus takes care of the case where jd1 and jd2 are no longer quite as expected. And it does in fact do this, so I guess here one is mostly guarding against the case where jd1 and jd2 would be swapped or so.
In any case, it doesn't really matter - an object array of timedelta is going to be so slow to deal with that an extra call to day_frac will not add much.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p.s. Let's remove the .item() - I'm fairly sure it is a copy&paste mistake from the other direction, where, since one deals with objects, it makes sense to get the actual timedelta out.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sort of want to create a custom format that constructs non-normalized jd1/jd2 and see how much stuff subtly breaks. The ERFA test case in test_sidereal is one example, this suggested implementation is another, I wonder how much else is baked in to our code base? Not everything, most stuff would be fine.

Comment thread astropy/time/tests/test_precision.py Outdated
assert abs(t2.jd2) < 0.5 or t2.jd1 % 2 == 0


def test_datetime_difference_agrees_with_timedelta_no_hypothesis():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick, but omit _no_hypothesis() (at the very least for this PR!).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's all a bit awkward because I don't trust this to be a useful test; it's the hypothesis version that is the real test, and I wouldn't have recommended merging this until it passed the hypothesis testing. So this clone is largely decorative.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't quite disagree - this was a test that showed the previous implementation was wrong, so it is good to guard against regression regardless!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, but I think it takes the hypothesis tests to be confident of avoiding regression. And they exist, maintained in parallel to this one.

Comment thread astropy/time/tests/test_precision.py Outdated
@mhvk

mhvk commented Nov 26, 2019

Copy link
Copy Markdown
Contributor

I think this is a bug fix, and thus needs a changelog entry. Since it is not release critical, let's aim for 4.0.1 - @bsipocz mentioned earlier she'll try to put in anything from 4.0.1 that is in before the release critical fixes have been made, so with a bit of luck, it will still be there from day 1.

@bsipocz

bsipocz commented Nov 26, 2019

Copy link
Copy Markdown
Member

@mhvk - timing wise I aim for the release to be finalized during the coordination meeting (well, definitely not sooner, looking at the wiki we still miss some important testing feedback).

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks all OK to me now. Thanks!

@mhvk
mhvk merged commit d6ef321 into astropy:master Nov 27, 2019
@bsipocz bsipocz modified the milestones: v4.0.1, v4.0 Nov 27, 2019
bsipocz pushed a commit that referenced this pull request Dec 1, 2019
Fix TimeDelta accuracy issue with datetime.timedelta
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

datetime -> Time accuracy problems

4 participants