From b71dbc198c433d6f67b04190099b644132e9c0b1 Mon Sep 17 00:00:00 2001 From: Bill-Gray Date: Mon, 15 Apr 2024 12:47:07 -0400 Subject: [PATCH] Improved macros for determing MJD from year/month. This extends the range over which the macros can be used. Also, there were slight differences in the definitions and usable time spans in the three files where they're used. --- delta_t.cpp | 19 +++++++++++-------- utc_algo.cpp | 16 ++++++++++------ utc_test.cpp | 35 +++++++++++++++++++---------------- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/delta_t.cpp b/delta_t.cpp index 242018e..4dd34ce 100644 --- a/delta_t.cpp +++ b/delta_t.cpp @@ -361,14 +361,17 @@ long double DLL_FUNC tdb_minus_tdt( const long double t_centuries) return( rval); /* difference is in _seconds_ */ } -/* These macros determine the MJD of the given date in 'YEAR'. They're -valid for years after -9999 in the _Gregorian_ calendar. Note that -we use the fact that February 1 is always 31 days after January 1, -but work backward from January 1 of the following year to get -March to December without having to consider leap days. */ - -#define JAN_1( YEAR) (((YEAR) * 365 + ((YEAR) + 9999) / 4 - ((YEAR) + 9999) / 100 \ - + ((YEAR) + 9999) / 400) - 681365) +/* These macros determine the MJD of the given date in 'YEAR'. They +are valid for (Gregorian) years after roughly 20 billion years ago. +This was chosen to comfortably include all dates since the Big Bang. +We use the fact that February 1 is always 31 days after January 1, +but have to work backward from January 1 of the following year to +get March to December without having to consider leap days. */ + +#define BASE_YEAR 19999999999L +#define JAN_1( YEAR) (((YEAR) * 365L + ((YEAR) + BASE_YEAR) / 4L - ((YEAR) + BASE_YEAR) / 100L \ + + ((YEAR) + BASE_YEAR) / 400L) - 678940L \ + - ((BASE_YEAR + 1L) / 400L) * 97L) #define FEB_1( YEAR) (JAN_1( YEAR) + 31) #define DEC_1( YEAR) (JAN_1( (YEAR)+1) - 31) #define NOV_1( YEAR) (DEC_1( YEAR) - 30) diff --git a/utc_algo.cpp b/utc_algo.cpp index a8f8e90..cd3438c 100644 --- a/utc_algo.cpp +++ b/utc_algo.cpp @@ -57,10 +57,14 @@ up with a UTC offset that'll keep |UTC-UT| < .5 second; i.e., keep UTC and UT as close together as possible. This is admittedly something of a kludge. But anything done to estimate -future leap seconds has to be a kludge; there's no "good" way to do it. */ +future leap seconds has to be a kludge; there's no "good" way to do it. -#define JAN_1( YEAR) (((YEAR) * 365 + ((YEAR) - 1) / 4 - ((YEAR) - 1) / 100 \ - + ((YEAR) - 1) / 400) - 678940) + See 'delta_t.cpp' for an explanation of the following macro. */ + +#define BASE_YEAR 19999999999L +#define JAN_1( YEAR) (((YEAR) * 365L + ((YEAR) + BASE_YEAR) / 4L - ((YEAR) + BASE_YEAR) / 100L \ + + ((YEAR) + BASE_YEAR) / 400L) - 678940L \ + - ((BASE_YEAR + 1L) / 400L) * 97L) // unsigned day = mjd + 1931367u + 2400000u; // int year = (int)( day * 400u / 146097u) - 10000; @@ -77,12 +81,12 @@ int main( const int argc, const char **argv) printf( "Year = %d\n", year); low = JAN_1( year); - printf( "MJD 1 Jan %d = %d\n", year, JAN_1( year)); + printf( "MJD 1 Jan %d = %ld\n", year, JAN_1( year)); if( mjd < low) { year--; low = JAN_1( year); - printf( "MJD 1 Jan %d = %d\n", year, JAN_1( year)); + printf( "MJD 1 Jan %d = %ld\n", year, JAN_1( year)); } high = JAN_1( year + 1); printf( "MJD 1 Jan %d = %d\n", year + 1, high); @@ -109,7 +113,7 @@ int main( const int argc, const char **argv) n_less++; mjd++; } - printf( "%d %d\n", n_more, n_less); + printf( "%d cases went over; %d went under\n", n_more, n_less); } return( 0); } diff --git a/utc_test.cpp b/utc_test.cpp index 45b624d..7813d77 100644 --- a/utc_test.cpp +++ b/utc_test.cpp @@ -15,24 +15,27 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* These macros determine the MJD of the given date in 'YEAR'. */ -/* They're valid for _non-negative_ years in the _Gregorian_ calendar. */ -/* Some are not used here, and therefore commented out, just to */ -/* avoid compiler warnings. */ +/* These macros determine the MJD of the given date in 'YEAR'. +They are explained a bit in comments in 'delta_t.cpp' (q.v.). +We're only using the July and January ones (the months in which +leap seconds occur). Unused macros are commented out, just to +avoid nuisance compiler warnings. */ -#define JAN_1( YEAR) (((YEAR) * 365 + ((YEAR) - 1) / 4 - ((YEAR) - 1) / 100 \ - + ((YEAR) - 1) / 400) - 678940) +#define BASE_YEAR 19999999999L +#define JAN_1( YEAR) (((YEAR) * 365L + ((YEAR) + BASE_YEAR) / 4L - ((YEAR) + BASE_YEAR) / 100L \ + + ((YEAR) + BASE_YEAR) / 400L) - 678940L \ + - ((BASE_YEAR + 1L) / 400L) * 97L) // #define FEB_1( YEAR) (JAN_1( YEAR) + 31) -#define MAR_1( YEAR) (((YEAR)*365 + (YEAR)/4 - (YEAR)/100 + (YEAR)/400) - 678881) -#define APR_1( YEAR) (MAR_1( YEAR) + 31) -#define MAY_1( YEAR) (APR_1( YEAR) + 30) -#define JUN_1( YEAR) (MAY_1( YEAR) + 31) -#define JUL_1( YEAR) (JUN_1( YEAR) + 30) -// #define AUG_1( YEAR) (JUL_1( YEAR) + 31) -// #define SEP_1( YEAR) (AUG_1( YEAR) + 31) -// #define OCT_1( YEAR) (SEP_1( YEAR) + 30) -// #define NOV_1( YEAR) (OCT_1( YEAR) + 31) -// #define DEC_1( YEAR) (NOV_1( YEAR) + 30) +#define DEC_1( YEAR) (JAN_1( (YEAR)+1) - 31) +#define NOV_1( YEAR) (DEC_1( YEAR) - 30) +#define OCT_1( YEAR) (NOV_1( YEAR) - 31) +#define SEP_1( YEAR) (OCT_1( YEAR) - 30) +#define AUG_1( YEAR) (SEP_1( YEAR) - 31) +#define JUL_1( YEAR) (AUG_1( YEAR) - 31) +// #define JUN_1( YEAR) (JUL_1( YEAR) - 30) +// #define MAY_1( YEAR) (JUN_1( YEAR) - 31) +// #define APR_1( YEAR) (MAY_1( YEAR) - 30) +// #define MAR_1( YEAR) (APR_1( YEAR) - 31) #include #include