Skip to content

Time scale conversion violates |jd2|<=0.5 #9533

Closed

Description

@aarchiba

Description

Upon construction, all Time objects contain two double-precision values, jd1 and jd2. These satisfy, and are tested to satisfy, the invariant that jd1 is an integer, abs(jd2)<=0.5, and if abs(jd2)==0.5 then jd1 is even. This is enforced by application of the not-publicly-documented function day_frac.

When a Time object is converted from one timescale to another, though, under some circumstances abs(jd2)>0.5.

>>> from astropy.time import Time
>>> t = Time(2441316.5, 0, scale='tai', format='jd')
>>> t.tcb.jd2
0.500344155968967

This was revealed by #9532 .

Expected behavior

t.tcb.jd2 should be made less than 0.5 by calling day_frac.

Actual behavior

The value violates the invariant.

System Details

$ python
Python 3.7.3 (default, Apr  3 2019, 05:39:12) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import platform; print(platform.platform())
Linux-5.0.0-31-generic-x86_64-with-Ubuntu-19.04-disco
>>> import sys; print("Python", sys.version)
Python 3.7.3 (default, Apr  3 2019, 05:39:12) 
[GCC 8.3.0]
>>> import numpy; print("Numpy", numpy.__version__)
Numpy 1.17.1
>>> import scipy; print("Scipy", scipy.__version__)
Scipy 1.3.1
>>> import astropy; print("astropy", astropy.__version__)
astropy 4.0.dev26770
>>>

Activity

  1. pllim commented on Nov 5, 2019

    @pllim
    Member
  2. aarchiba commented on Nov 5, 2019

    @aarchiba
    ContributorAuthor

    Fixing this is a little bit subtle because during conversion new Time objects are constructed with from_jd=True, in which case almost no validation is done, and existing tests check whether the original arrays remain untouched. So any time from_jd is True is an opportunity for the constructed objects to violate Time invariants, though the custom format validation code has caught some cases. The idea is, I think, that from_jd=True construction should be internal and efficient and maybe involve already-converted data.

    Alternatively one could track down where (non-custom) scale conversion is done and fix that so that it always maintained the invariant. That won't prevent users from creating silently non-conformant Time objects with badly implemented custom scales. Most code probably doesn't actually care whether jd1 is an integer or half-integer, but some certainly does, and that code will break.

  3. mhvk commented on Nov 5, 2019

    @mhvk
    Contributor

    Nice find. Indeed, a missing day_frac call after the scale change. Note that I don't think we ever promised the fraction would always be <=0.5, though we've certainly made efforts to ensure it does on input. For precision purposes, it may not help much - one bit of precision has already been lost by the erfa routine. But it may make sense to try to make this more of a promise and thus to fix this.

  4. aarchiba commented on Nov 8, 2019

    @aarchiba
    ContributorAuthor

    Now fixed in #9532 ; it's a one-line fix. I didn't add general validation, so custom formats can still make jd2>jd1 (for example).

  5. pllim commented on Nov 8, 2019

    @pllim
    Member

    @aarchiba , given that #9532 might be open for a while yet, is it possible for you to submit the one-liner bug fix as its own PR? Thanks!

  6. added a commit that references this issue on Nov 9, 2019
    ee6e205
  7. added a commit that references this issue on Jan 6, 2020
    5d7a4b2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions