Tuesday, January 05, 2021

[cbhhtttg] Terrestrial Time Julian Dates

JD(TT) means Julian Date with the Terrestrial Time time system.  We guess that it is the most popular time system that is expressed as a single number (making arithmetic simple) and is constantly increasing (not held back during leap seconds, as Unix Time (posix mode) is), because astronomers use both TT and JD.  (But do they actually combine the two?)

The following command demonstrates converting a local time to JD(TT) using GNU date and perl.  (Previously, converting to plain Terrestrial Time, without the subsequent step of converting TT to a Julian Date.)  We demonstrate conversions across the leap second which occurred at 2015-06-30 18:59:60 local time in Chicago (Central Daylight Time).  One can see that JD(TT) advances uniformly through the leap second.

$ date --date='TZ="right/America/Chicago" 2015-06-30T18:59:59-05:00' +%s.%N | perl -nlwe 'printf("JD(TT) = %f\n",($_-(946728000-10-32.184))/60/60/24+2451545)'
JD(TT) = 2457204.500766

$ date --date='TZ="right/America/Chicago" 2015-06-30T18:59:60-05:00' +%s.%N | perl -nlwe 'printf("JD(TT) = %f\n",($_-(946728000-10-32.184))/60/60/24+2451545)'
JD(TT) = 2457204.500778

$ date --date='TZ="right/America/Chicago" 2015-06-30T19:00:00-05:00' +%s.%N | perl -nlwe 'printf("JD(TT) = %f\n",($_-(946728000-10-32.184))/60/60/24+2451545)'
JD(TT) = 2457204.500789

Update: conversions using the bc arbitrary precision calculator utility instead of perl.  This correctly handles the nanosecond precision emitted by date %N.

$ echo -n 'JD(TT) = '; echo 'scale=14;('$(date --date='TZ="right/America/Chicago" 2015-06-30T18:59:59' +%s.%N)'-(946728000-10-32.184))/60/60/24+2451545' | bc
JD(TT) = 2457204.50076601851851

$ echo -n 'JD(TT) = '; echo 'scale=14;('$(date --date='TZ="right/America/Chicago" 2015-06-30T18:59:60' +%s.%N)'-(946728000-10-32.184))/60/60/24+2451545' | bc
JD(TT) = 2457204.50077759259259

$ echo -n 'JD(TT) = '; echo 'scale=14;('$(date --date='TZ="right/America/Chicago" 2015-06-30T19:00:00' +%s.%N)'-(946728000-10-32.184))/60/60/24+2451545' | bc
JD(TT) = 2457204.50078916666666

Here is how to get the current time as JD(TT):

echo -n 'JD(TT) = '; echo 'scale=14;('$(date --date='TZ="right/UTC" '$(date -u --iso=ns) +%s.%N)'-(946728000-10-32.184))/60/60/24+2451545' | bc

In any time system, Julian Date 2451545.0 always corresponds to exactly noon on January 1, 2000 in that time system.  (For example JD(America/Chicago) 2451545.0 means noon, Central Standard Time, on January 1, 2000.)  We derive the Unix Time corresponding to JD 2451545.0 as follows, yielding the constant 946728000 seen in the conversion routine above.

$ date --date='TZ="posix/UTC" 2000-01-01T12:00:00' +%s
946728000

To do: explain why posix/UTC is the correct time zone to use for the conversion above, and why the environment time zone does not matter.

We verify that the conversion routine above is correct.  We know that noon, Terrestrial Time on January 1, 2000 corresponds to JD(TT) 2451545.0.  First, we convert noon TT to UTC:

$ TZ=right/UTC date --iso=ns --date='TZ="posix/UTC" -32.184 second -10 second 2000-01-01T12:00:00'
2000-01-01T11:58:55,816000000+00:00

Then we feed that UTC time into the conversion command above, getting the correct output:

$ date --date='TZ="right/UTC" 2000-01-01T11:58:55.816+00:00' +%s.%N | perl -nlwe 'printf("JD(TT) = %f\n",($_-(946728000-10-32.184))/60/60/24+2451545)'
JD(TT) = 2451545.000000

Here is how to do the reverse conversion, going from JD(TT) to local time.  Local time zones are defined as offsets from UTC, so they observe leap seconds.

$ TZ=right/America/Chicago date --iso=ns --date=@$(echo 2457204.5007790214906134259259259259259 | perl -plwe '$_=($_-2451545.0)*60*60*24+(946728000-10-32.184)')
2015-06-30T18:59:60,123460000-05:00

The high precision input JD(TT) corresponds to 123456789 nanoseconds into the leap second; precision loss occurs during conversion.

Update: same calculation using bc.  The final digit of nanoseconds is wrong likely because date truncates input when reading nanoseconds.

$ TZ=right/America/Chicago date --iso=ns --date=@$(echo 'scale=14;(2457204.5007790214906134259259259259259-2451545.0)*60*60*24+(946728000-10-32.184)'| bc)
2015-06-30T18:59:60,123456788-05:00

Note that GNU date uses the proleptic Gregorian calendar for all dates,

date --date='TZ="posix/UTC" 1500-02-29T12:00:00'
date: invalid date 'TZ="posix/UTC" 1500-02-29T12:00:00'

so conversions from Julian Dates in the distant past will produce output corresponding to a calendar that had not yet invented.  (Julian Dates have nothing to do with the Julian calendar.)  In the same vein, to convert a local calendar date and time in the distant past to JD(TT), one must first convert the local calendar date and time to the proleptic Gregorian calendar.  GNU date does not provide such calendar conversion functions.

JD(TAI), the Julian Date with the International Atomic Time time system, also might be popular.  To use it, simply omit the offset 32.184 from the Terrestrial Time conversion routines above.

No comments :