diff --git a/doc/source/_assets/timescale-refs.bib b/doc/source/_assets/timescale-refs.bib index b7bd7f5..1483fb1 100644 --- a/doc/source/_assets/timescale-refs.bib +++ b/doc/source/_assets/timescale-refs.bib @@ -15,6 +15,20 @@ @book{Dershowitz:2007cc publisher = {Cambridge University Press}, edition = {3}, } +@article{Desai:2015jr, +author = {Desai, S and Wahr, J and Beckley, B}, +title = {{Revisiting the pole tide for and from satellite altimetry}}, +journal = {Journal of Geodesy}, +year = {2015}, +month = dec, +volume = {89}, +number = {12}, +issn = {0949-7714}, +url = {https://doi.org/10.1007/s00190-015-0848-7}, +doi = {10.1007/s00190-015-0848-7}, +pages = {1233--1243}, +publisher = {Springer Science and Business Media LLC}, +} @article{Fairhead:1990vz, author = {Fairhead, L and Bretagnon, P}, title = {{An analytical formula for the time transformation TB-TT}}, @@ -49,6 +63,19 @@ @techreport{Kaplan:2005kj institution = {US Naval Observatory}, pages = {116}, } +@article{Lieske:1979wv, +author = {Lieske, J H}, +title = {{Precession matrix based on IAU (1976) system of astronomical constants}}, +journal = {Astronomy and Astrophysics}, +year = {1979}, +month = mar, +volume = {73}, +number = {3}, +url = {https://ui.adsabs.harvard.edu/abs/1979A&A....73..282L}, +key = {1979A&A....73..282L}, +pages = {282--284}, +note = {Provided by the SAO/NASA Astrophysics Data System}, +} @book{Meeus:1991vh, author = {Meeus, J H}, title = {{Astronomical Algorithms}}, diff --git a/test/test_time.py b/test/test_time.py index fa85851..453a35f 100644 --- a/test/test_time.py +++ b/test/test_time.py @@ -245,6 +245,27 @@ def test_sidereal(): expected = 20.96154017401333 assert np.isclose(expected, 24.0*ts.st).all() +def test_besselian(): + """Test that the Besselian year matches expected outputs + """ + # Besselian years + B = np.array([1900.0, 1950.0, 2000.0]) + # create timescale from Besselian year + ts = timescale.from_besselian(B) + # expected Julian date for Besselian year 1900 + # from table 1 of Lieske (1979) + expected = np.array([2415020.31352, 2433282.42345905, 2451544.5333981]) + assert np.isclose(expected, ts.utc).all() + # check Besselian year + assert np.isclose(ts.B, B).all() + # check inverse conversions + JD = np.array([2415020.0, 2433282.5, 2451545.0]) + ts = timescale.from_julian(JD) + # check Besselian year from Julian date + # from table 1 of Lieske (1979) + expected = np.array([1899.999142, 1950.00021, 2000.001278]) + assert np.isclose(expected, ts.B).all() + def test_epochs(): """Test that the epoch conversions match expected outputs """ diff --git a/timescale/__init__.py b/timescale/__init__.py index f43f8eb..0d26f5d 100644 --- a/timescale/__init__.py +++ b/timescale/__init__.py @@ -20,6 +20,13 @@ def from_deltatime(*args, **kwargs): # Julian dates def from_julian(ut1, **kwargs): return timescale.time.Timescale(ut1 - 2400000.5) +# Besselian years +def from_besselian(B, **kwargs): + """Wrapper for creating a ``Timescale`` object from Besselian years + """ + # convert Besselian year to MJD + MJD = 15019.81352 + (B - 1900.0) * 365.242198781 + return timescale.time.Timescale(MJD) # calendar dates def from_calendar(*args, **kwargs): """Wrapper for ``timescale.time.Timescale().from_calendar`` diff --git a/timescale/time.py b/timescale/time.py index b7118a5..51b86bf 100755 --- a/timescale/time.py +++ b/timescale/time.py @@ -17,6 +17,7 @@ UPDATE HISTORY: Updated 07/2025: verify Bulletin-A entries are not already in merged file + add Besselian year conversion to Timescale class Updated 03/2025: added attributes for ut1_utc and gps_utc Updated 02/2025: added GLONASS as delta time option update GPS seconds calculation for output from timescale object @@ -1073,6 +1074,12 @@ def T(self): """ _jd_j2000 = _jd_mjd + _mjd_j2000 return (self.tt - _jd_j2000)/self.century + + @timescale.utilities.reify + def B(self): + """Time in Besselian years :cite:p:`Lieske:1979wv` + """ + return 1900.0 + (self.MJD - 15019.81352) / 365.242198781 @timescale.utilities.reify def ut1(self): @@ -1080,6 +1087,15 @@ def ut1(self): """ # convert UT1-UTC to days return self.utc + self.ut1_utc/self.day + + @timescale.utilities.reify + def ut2(self): + """UT0 corrected for polar motion and seasonal variation + """ + theta = 2.0*np.pi*self.B + ut2_ut1 = 0.022*np.sin(theta) - 0.012*np.cos(theta) - \ + 0.006*np.sin(2.0*theta) + 0.007*np.cos(2.0*theta) + return self.ut1 + ut2_ut1 @timescale.utilities.reify def utc(self):