astropy / astropy

Astronomy and astrophysics core library
https://www.astropy.org
BSD 3-Clause "New" or "Revised" License
4.46k stars 1.78k forks source link

J2000 Epoch is defined wrong for UTC #17422

Closed BrofessorDoucette closed 1 day ago

BrofessorDoucette commented 1 day ago

Description

https://en.wikipedia.org/wiki/Equinox_(celestial_coordinates)

Wikipedia page says that J2000 should be defined in UTC as January 1st, 2000 at 11:58:55. However it is returned in astropy as a datetime object holding January 1st 2000, at 12:00:00 UTC. Leading to a discrepancy of over a minute.

https://en.wikipedia.org/wiki/Leap_second

In addition, I'm pretty sure that 5 extra leap seconds are being added to datetime objects when converting astropy Times to datetime objects. Only 27 leap seconds should be added to UTC. Likely this difference arises because TT is 32 seconds ahead of TAI. While UTC is 37 seconds ahead of TAI. While I'm not familiar with all of astropy's code, I get this idea because the CDFEpoch library: https://cdflib.readthedocs.io/en/latest/api/cdflib.epochs.CDFepoch.html; defines a variable J2000LeapSeconds= 32.0. However, CDFEpoch also offers to use astropy internally for the conversion, and I'm guessing their implementation was designed to match astropy's as they offer both: https://cdflib.readthedocs.io/en/latest/api/cdflib.epochs_astropy.CDFAstropy.html#cdflib.epochs_astropy.CDFAstropy

Expected behavior

Datetime objects in python are to hold UTC times by default, users will expect the times to be in UTC; NOT Terrestrial Time

How to Reproduce

import astropy
import astropy.time

t = astropy.time.Time(2451545.0, format="jd", scale="utc")

print(t.datetime)
2000-01-01 12:00:00

Notice that it says January 1st, 2000 at 12:00:00 rather than January 1st, 2000 at 11:58:55. Also notice that autoplot disagrees with astropy by 1 minute and 9 seconds when converting a CDF_TT2000 epoch to UTC. Likely this is because the autoplot team is defining J2000 correctly and only adding 27 leap seconds to UTC for the present date rather than 32.

Versions

import astropy
try:
    astropy.system_info()
except AttributeError:
    import platform; print(platform.platform())
    import sys; print("Python", sys.version)
    import astropy; print("astropy", astropy.__version__)
    import numpy; print("Numpy", numpy.__version__)
    import erfa; print("pyerfa", erfa.__version__)
    try:
        import scipy
        print("Scipy", scipy.__version__)
    except ImportError:
        print("Scipy not installed")
    try:
        import matplotlib
        print("Matplotlib", matplotlib.__version__)
    except ImportError:
        print("Matplotlib not installed")
Windows-11-10.0.22631-SP0
Python 3.12.5 (tags/v3.12.5:ff3bc82, Aug  6 2024, 20:45:27) [MSC v.1940 64 bit (AMD64)]
astropy 6.1.2
Numpy 1.26.4
pyerfa 2.0.1.4
Scipy 1.14.0
Matplotlib 3.9.2
github-actions[bot] commented 1 day ago

Welcome to Astropy 👋 and thank you for your first issue!

A project member will respond to you as soon as possible; in the meantime, please double-check the guidelines for submitting issues and make sure you've provided the requested details.

GitHub issues in the Astropy repository are used to track bug reports and feature requests; If your issue poses a question about how to use Astropy, please instead raise your question in the Astropy Discourse user forum and close this issue.

If you feel that this issue has not been responded to in a timely manner, please send a message directly to the development mailing list. If the issue is urgent or sensitive in nature (e.g., a security vulnerability) please send an e-mail directly to the private e-mail feedback@astropy.org.

ayshih commented 1 day ago

Regarding J2000.0, you haven't created the time that you think you have. astropy.time.Time(2451545.0, format="jd", scale="utc") expressly creates a Time instance for JD 2451545.0 UTC (because you have specified scale="utc"), but J2000.0 is defined as JD 2451545.0 TT (i.e., Terrestrial Time, not Coordinated Universal Time). So, the correct code is:

>>> t = astropy.time.Time(2451545.0, format="jd", scale="tt")
>>> print(t.utc.datetime)
2000-01-01 11:58:55.816000

Note that you also have to explicitly convert the time to UTC (t.utc) before converting it to a datetime.datetime instance.

Instead of typing out the JD, you can alternatively simply use the "J2000" shorthand:

>>> t = astropy.time.Time("J2000", scale="tt")
>>> print(t.utc.datetime)
2000-01-01 11:58:55.816000

I stress again that if you want to create a Time instance for the J2000.0 epoch, you need to explicitly specify scale="tt".

Regarding leapseconds, you'll have to share some code or reference for why you think Astropy is incorrect. As you can see above, Astropy can report exactly the correct UTC time for J2000.0.