From 94668b899cdeba02cd552b0f7c196c424c1974c5 Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Fri, 28 Nov 2025 10:14:05 +0100 Subject: [PATCH 01/16] src: allow for year = 0 A previous fix for issue 1538 incorrectly rules out year = 0; Removed that restriction. Signed-off-by: Ed@vanGasteren.net --- src/datetime.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/datetime.cc b/src/datetime.cc index d97998d44..aed75f73a 100644 --- a/src/datetime.cc +++ b/src/datetime.cc @@ -132,7 +132,7 @@ uint to_date(object_p dtobj, dt_t &dt, tm_t &tm, bool error) const uint days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; bool bisext = m == 2 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); - if (m < 1 || m > 12 || d < 1 || d > days[m-1] + bisext || y == 0) + if (m < 1 || m > 12 || d < 1 || d > days[m-1] + bisext) { if (error) rt.invalid_date_error(); @@ -624,11 +624,6 @@ size_t render_date(renderer &r, algebraic_g date) uint month = date->as_uint32(0, false) % 100; date = date / factor; uint year = date->as_uint32(0, false); - if (year == 0) - { - rt.invalid_date_error(); - return 0; - } char mname[4]; if (Settings.ShowMonthName() && month >=1 && month <= 12) From 7cb41e4699d03e7e0908062e7cddff126a8241c9 Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Fri, 28 Nov 2025 17:36:41 +0100 Subject: [PATCH 02/16] src: change BC to B(efore) C(ommon) E(ra) BCE is a secular, non-religious alternative to BC, and both systems use the same year numbers, simply with different terminology. BCE is considered more inclusive as it does not reference Christianity. Signed-off-by: Ed@vanGasteren.net --- src/datetime.cc | 2 +- src/tests.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/datetime.cc b/src/datetime.cc index aed75f73a..582804e1d 100644 --- a/src/datetime.cc +++ b/src/datetime.cc @@ -655,7 +655,7 @@ size_t render_date(renderer &r, algebraic_g date) case 3: r.printf("%s%c%s%c%u", ytext, sep, mname, sep, day); break; } if (neg) - r.printf(" BC"); + r.printf(" BCE"); if (time && !time->is_zero()) { diff --git a/src/tests.cc b/src/tests.cc index 441d5329d..b52e201b1 100644 --- a/src/tests.cc +++ b/src/tests.cc @@ -10134,7 +10134,7 @@ void tests::date_operations() .expect("2 460 938"); step("Converting from a Julian day number to a date") .test(CLEAR, "1 000 000", ENTER, ID_DateFromJulianDayNumber) - .expect("Tue 21/Oct/1975 BC"); + .expect("Tue 21/Oct/1975 BCE"); step("Adding invalid dates") .test(CLEAR, "1 2 DATE+", ENTER) .error("Invalid date"); From ae688aa6617c921cd59d7c9377d94f972d0df1f5 Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Sat, 29 Nov 2025 21:17:36 +0100 Subject: [PATCH 03/16] src: Better handling of the BCE - CE timeline The BCE - CE timeline doesn't have a year = 0. So years <= 0 are shifted. That wasn't handled properly. Introduced setting AstronomicalYearNumbering (default) vs BCECEyearNumbering. With AstronomicalYearNumbering the timeline is a uniform number line. Years < 0 are presented, on the stack, with there sign. With BCECEyearNumbering years <= 0 are presented shifted, whithout a sign and with a BCE indicator. Years > 0 get a CE indicator. See: https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar and https://en.wikipedia.org/wiki/Astronomical_year_numbering Signed-off-by: Ed@vanGasteren.net --- src/datetime.cc | 42 +++++++++++++++++++++++++++--------------- src/ids.tbl | 1 + src/tests.cc | 5 ++++- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/datetime.cc b/src/datetime.cc index 582804e1d..7c65e91c8 100644 --- a/src/datetime.cc +++ b/src/datetime.cc @@ -609,8 +609,9 @@ size_t render_date(renderer &r, algebraic_g date) { if (!date || !date->is_real()) return 0; - bool neg = date->is_negative(); - if (neg) + + bool negativeDate = date->is_negative(); + if (negativeDate) date = -date; algebraic_g factor = integer::make(100); @@ -623,7 +624,15 @@ size_t render_date(renderer &r, algebraic_g date) date = date / factor; uint month = date->as_uint32(0, false) % 100; date = date / factor; - uint year = date->as_uint32(0, false); + int year = date->as_uint32(0, false); + + if (Settings.ShowDayOfWeek()) + { + int syear = negativeDate ? -int(year) : year; + ularge jdn = julian_day_number(day, month, syear); + uint dow = jdn % 7; + r.printf("%s ", get_wday_shortcut(dow)); + } char mname[4]; if (Settings.ShowMonthName() && month >=1 && month <= 12) @@ -631,19 +640,17 @@ size_t render_date(renderer &r, algebraic_g date) else snprintf(mname, 4, "%u", month); + bool zeroYear = year == 0; + if ((negativeDate || zeroYear) && Settings.BCECEyearNumbering()) + year = year + 1; + if (negativeDate && Settings.AstronomicalYearNumbering()) + year = - year; + char ytext[16]; if (Settings.TwoDigitYear()) - snprintf(ytext, sizeof(ytext), "%02u", year % 100); + snprintf(ytext, sizeof(ytext), "%02i", year % 100); else - snprintf(ytext, sizeof(ytext), "%u", year); - - if (Settings.ShowDayOfWeek()) - { - int syear = neg ? -int(year) : year; - ularge jdn = julian_day_number(day, month, syear); - uint dow = jdn % 7; - r.printf("%s ", get_wday_shortcut(dow)); - } + snprintf(ytext, sizeof(ytext), "%i", year); char sep = Settings.DateSeparator(); uint index = 2 * Settings.YearFirst() + Settings.MonthBeforeDay(); @@ -654,8 +661,13 @@ size_t render_date(renderer &r, algebraic_g date) case 2: r.printf("%s%c%u%c%s", ytext, sep, day, sep, mname); break; case 3: r.printf("%s%c%s%c%u", ytext, sep, mname, sep, day); break; } - if (neg) - r.printf(" BCE"); + if (Settings.BCECEyearNumbering()) + { + r.printf(" "); + if (negativeDate || zeroYear) + r.printf("B"); + r.printf("CE"); + } if (time && !time->is_zero()) { diff --git a/src/ids.tbl b/src/ids.tbl index e26e6bac7..5963fafc2 100644 --- a/src/ids.tbl +++ b/src/ids.tbl @@ -1040,6 +1040,7 @@ FLAG(NumericalIntegration, SymbolicIntegration) FLAG(TVMPayAtBeginningOfPeriod, TVMPayAtEndOfPeriod) FLAG(TruthLogicForIntegers, BitwiseLogicForIntegers) FLAG(LaxArrayResizing, StrictArrayResizing) +FLAG(BCECEyearNumbering, AstronomicalYearNumbering) ALIAS(HardwareFloatingPoint, "HFP") ALIAS(HardwareFloatingPoint, "HardFP") diff --git a/src/tests.cc b/src/tests.cc index b52e201b1..b06f69407 100644 --- a/src/tests.cc +++ b/src/tests.cc @@ -10134,7 +10134,10 @@ void tests::date_operations() .expect("2 460 938"); step("Converting from a Julian day number to a date") .test(CLEAR, "1 000 000", ENTER, ID_DateFromJulianDayNumber) - .expect("Tue 21/Oct/1975 BCE"); + .expect("Tue 21/Oct/-1975"); + step("Change to BCECE representation") + .test(ID_BCECEyearNumbering) + .expect("Tue 21/Oct/1976 BCE"); step("Adding invalid dates") .test(CLEAR, "1 2 DATE+", ENTER) .error("Invalid date"); From fc6e1338bf8600d5e448d0518ca424d1e86f38aa Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Sun, 30 Nov 2025 11:46:29 +0100 Subject: [PATCH 04/16] src: correct the label for the DateMenu There where inconsistent labels for the DateMenu. Corrected those. Signed-off-by: Ed@vanGasteren.net --- src/menu.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/menu.cc b/src/menu.cc index 35361fe4d..61d50690b 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -1771,7 +1771,7 @@ MENU(TimeMenu, "→Time", ID_SetTime, "→Date", ID_SetDate, "ClkAdj", ID_Unimplemented, - "Dates", ID_DateMenu, + "Date", ID_DateMenu, "Alarms", ID_AlarmMenu); From 2f713b53b25d5823fd5c1b2cb52df81089a87061 Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Sun, 30 Nov 2025 17:49:20 +0100 Subject: [PATCH 05/16] doc: improve Date and Time documentation A step towards a more complete documentation of the Date and Time related command and settings. Signed-off-by: Ed@vanGasteren.net --- doc/commands/system.md | 60 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/doc/commands/system.md b/doc/commands/system.md index 804bc3be6..35744deda 100755 --- a/doc/commands/system.md +++ b/doc/commands/system.md @@ -1,7 +1,10 @@ + # Time, Date, Alarms and System Commands ## DateMenu +Activated from the [Time](##TimeMenu) menu. + Show a softkey menu for date-related commands, including: * `Date` @@ -14,7 +17,9 @@ Show a softkey menu for date-related commands, including: ## TimeMenu -Show a softkey menu for time-related commands: +Activated by the 🟦 _V_ (_TIME_) key. + +Show a softkey menu for time-related commands, including: * `Time` * `ToHMS` @@ -28,14 +33,61 @@ Show a softkey menu for time-related commands: * `TimedEval` * `SetTime` +## Time, Date related flags -## Date format +* `HideDate` / `ShowDate` +* `HideTime` / `ShowTime` +* `ShowSeconds` / `HideSeconds` +* `Time12H` / `Time24H` +* `HideMonthName` / `ShowMonthName` +* `MonthBeforeDay` / `DayBeforeMonth` +* `YearFirst` / `YearLast` +* `TwoDigitYear` / `FourDigitYear` +* `HideDayOfWeek` / `ShowDayOfWeek` +* `BCECEyearNumbering` / `AstronomicalYearNumbering` -The date format is `YYYYMMDD`, with an optional fractional part defining the -time, as in `YYYYMMDD.HHMMSS`. +## Time, Date related settings + +* `DateSlash` / `DateDash` / `DateDot` / `DateSpace` + +## BCECEyearNumbering + +Activate the B(efore) C(ommon) E(ra) / C(ommon) E(ra) suffix of the year in the display of a date on the stack. +Activate the related year numbering which jumps from 1 BCE to 1 CE. So negative years are shifted. +See: [Proleptic Gregorian calendar](https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar) + +## AstronomicalYearNumbering + +Activate the Astronomical year numbering. This uses a uniform timeline including a year = 0. +Display negative years on the stack with a minus sign. +See: [Astronomical year numbering](https://en.wikipedia.org/wiki/Astronomical_year_numbering) + +## Date entry / edit format + +A whole number with a `_date` unit attached is interpreted as a date according to the customary format `YYYYMMDD`. +The year need not be a 4 digit number. +It can a smaller, bigger, zero, even a negative number and leading zeros can be ommitted +(as such it need not fit the `YYYY` format). Note: the date format is intentionally different from the format on the HP-48. +## Date display format + +By default a Date is displayed on the stack like `Sun 30/Nov/2025`. +The format can be adjusted by changing the [Time, Date related flags](## Time, Date related flags) or +[Time, Date related settings](## Time, Date related settings) + +## Date+Time entry / edit format + +A real number with a `_date` unit attached is interpreted as a Date + Time +according to the format `YYYYMMDD.HHMMSS` + +## Date+Time display format + +By default a Date+Time is displayed on the stack like `Sun 30/Nov/2025, 16:43:10`. +The format can be adjusted by changing the [Time, Date related flags](## Time, Date related flags) or / and +[Time, Date related settings](## Time, Date related settings). + ## Time format The time format is `HH.MMSS` with optional hundredths of a second as From f7203134881025a334ee2f8eacc58734f762d41a Mon Sep 17 00:00:00 2001 From: evgaster Date: Sun, 30 Nov 2025 21:47:57 +0100 Subject: [PATCH 06/16] Update system.md Signed-off-by: evgaster --- doc/commands/system.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/commands/system.md b/doc/commands/system.md index 35744deda..e001bc016 100755 --- a/doc/commands/system.md +++ b/doc/commands/system.md @@ -3,7 +3,7 @@ ## DateMenu -Activated from the [Time](##TimeMenu) menu. +Activated from the [Time](#TimeMenu) menu. Show a softkey menu for date-related commands, including: @@ -74,7 +74,7 @@ Note: the date format is intentionally different from the format on the HP-48. ## Date display format By default a Date is displayed on the stack like `Sun 30/Nov/2025`. -The format can be adjusted by changing the [Time, Date related flags](## Time, Date related flags) or +The format can be adjusted by changing the [Time, Date related flags](#"Time, Date related flags") or [Time, Date related settings](## Time, Date related settings) ## Date+Time entry / edit format @@ -85,7 +85,7 @@ according to the format `YYYYMMDD.HHMMSS` ## Date+Time display format By default a Date+Time is displayed on the stack like `Sun 30/Nov/2025, 16:43:10`. -The format can be adjusted by changing the [Time, Date related flags](## Time, Date related flags) or / and +The format can be adjusted by changing the [Time, Date related flags](#"Time, Date related flags") or / and [Time, Date related settings](## Time, Date related settings). ## Time format From 26def6cbea2723405b97da6c2f0527ff5344909b Mon Sep 17 00:00:00 2001 From: evgaster Date: Sun, 30 Nov 2025 21:49:42 +0100 Subject: [PATCH 07/16] Update system.md Signed-off-by: evgaster --- doc/commands/system.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/commands/system.md b/doc/commands/system.md index e001bc016..40e9f7062 100755 --- a/doc/commands/system.md +++ b/doc/commands/system.md @@ -74,8 +74,8 @@ Note: the date format is intentionally different from the format on the HP-48. ## Date display format By default a Date is displayed on the stack like `Sun 30/Nov/2025`. -The format can be adjusted by changing the [Time, Date related flags](#"Time, Date related flags") or -[Time, Date related settings](## Time, Date related settings) +The format can be adjusted by changing the ["Time, Date related flags"](#"Time, Date related flags") or +["Time, Date related settings"](#"Time, Date related settings") ## Date+Time entry / edit format From 3f0a82e874fca669c0a49a7111a026c1a60c960a Mon Sep 17 00:00:00 2001 From: evgaster Date: Sun, 30 Nov 2025 21:54:31 +0100 Subject: [PATCH 08/16] Update system.md Signed-off-by: evgaster --- doc/commands/system.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/commands/system.md b/doc/commands/system.md index 40e9f7062..483aab4d8 100755 --- a/doc/commands/system.md +++ b/doc/commands/system.md @@ -74,8 +74,8 @@ Note: the date format is intentionally different from the format on the HP-48. ## Date display format By default a Date is displayed on the stack like `Sun 30/Nov/2025`. -The format can be adjusted by changing the ["Time, Date related flags"](#"Time, Date related flags") or -["Time, Date related settings"](#"Time, Date related settings") +The format can be adjusted by changing the [Time, Date related flags](#time,-date-related-flags) or +[Time, Date related settings](#time,-date-related-settings) ## Date+Time entry / edit format From 8bf97b53187aded16b17a3d19be77407d3b16ba1 Mon Sep 17 00:00:00 2001 From: evgaster Date: Sun, 30 Nov 2025 21:57:50 +0100 Subject: [PATCH 09/16] Update system.md Signed-off-by: evgaster --- doc/commands/system.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/commands/system.md b/doc/commands/system.md index 483aab4d8..2f049d083 100755 --- a/doc/commands/system.md +++ b/doc/commands/system.md @@ -74,8 +74,8 @@ Note: the date format is intentionally different from the format on the HP-48. ## Date display format By default a Date is displayed on the stack like `Sun 30/Nov/2025`. -The format can be adjusted by changing the [Time, Date related flags](#time,-date-related-flags) or -[Time, Date related settings](#time,-date-related-settings) +The format can be adjusted by changing the [Time, Date related flags](#time-date-related-flags) or +[Time, Date related settings](#time-date-related-settings) ## Date+Time entry / edit format From 82a03f48ac7a94890523da8ba8fe2ae9ba408e5e Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Tue, 2 Dec 2025 12:30:52 +0100 Subject: [PATCH 10/16] doc: further improve Date and Time documentation Fixed internal links. Further explain handling of negative date. Signed-off-by: Ed@vanGasteren.net --- doc/commands/system.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/commands/system.md b/doc/commands/system.md index 2f049d083..e73cb59ab 100755 --- a/doc/commands/system.md +++ b/doc/commands/system.md @@ -68,6 +68,8 @@ A whole number with a `_date` unit attached is interpreted as a date according t The year need not be a 4 digit number. It can a smaller, bigger, zero, even a negative number and leading zeros can be ommitted (as such it need not fit the `YYYY` format). +In case of a negative number only the year is treated as such. +Months and days, even in a negative year, run from low (positive numbers) to high. Note: the date format is intentionally different from the format on the HP-48. @@ -80,13 +82,13 @@ The format can be adjusted by changing the [Time, Date related flags](#time-date ## Date+Time entry / edit format A real number with a `_date` unit attached is interpreted as a Date + Time -according to the format `YYYYMMDD.HHMMSS` +according to the format `YYYYMMDD.HHMMSS`. ## Date+Time display format By default a Date+Time is displayed on the stack like `Sun 30/Nov/2025, 16:43:10`. -The format can be adjusted by changing the [Time, Date related flags](#"Time, Date related flags") or / and -[Time, Date related settings](## Time, Date related settings). +The format can be adjusted by changing the [Time, Date related flags](#time-date-related-flags) or / and +[Time, Date related settings](#time-date-related-settings). ## Time format From 08fc3bc1fe0aac690376fa1c0b33cc1254007f5b Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Sun, 14 Dec 2025 13:42:13 +0100 Subject: [PATCH 11/16] src: change Julian date conversion to SOFA functions. Replaced the code that converts between Julian en Gregorian dates by functions from the Standards Of Fundamental Astronomy (SOFA) Libraries. See: https://www.iausofa.org/. Note: Because a Julian date starts at noon, the timeline is shifted by half a day or 12 hours with respect to the Gregorian timeline. Further minor code convention changes and documentation updates. Signed-off-by: Ed@vanGasteren.net --- doc/commands/system.md | 4 +- src/datetime.cc | 608 +++++++++++++++++++++++++++++++++++------ src/datetime.h | 26 +- src/tests.cc | 8 +- 4 files changed, 563 insertions(+), 83 deletions(-) diff --git a/doc/commands/system.md b/doc/commands/system.md index e73cb59ab..e0480c103 100755 --- a/doc/commands/system.md +++ b/doc/commands/system.md @@ -258,7 +258,7 @@ This command ignores that gap, so the Julian day number given by this command fo To compute the Julian Day Number for the first day of the millenium: ```rpl 20000101 JDN -@ Expecting 2 451 545 +@ Expecting 2 451 544 ¹/₂ ``` ## Datefromjuliandaynumber @@ -270,7 +270,7 @@ It is the opposite of the `JDN` command. ```rpl 2451545 JDN→ -@ Expecting Sat 1/Jan/2000 +@ Expecting Sat 1/Jan/2000, 12:00:00 ``` ## ACK diff --git a/src/datetime.cc b/src/datetime.cc index 7c65e91c8..21e6fa89d 100644 --- a/src/datetime.cc +++ b/src/datetime.cc @@ -201,9 +201,14 @@ algebraic_p julian_day_number(const dt_t &dt, const tm_t &tm) // Compute julian day number for a dt_t structure // ---------------------------------------------------------------------------- { + double jdn_value = julian_day_number(dt.day, dt.month, dt.year); + long jdn_day = long(jdn_value); + long jdn_fraction_of_day = long((jdn_value - jdn_day) * 8640000); + ularge csecs = (tm.hour * 3600 + tm.min * 60 + tm.sec) * 100 + tm.csec; - ularge jval = julian_day_number(dt.day, dt.month, dt.year); - algebraic_g jdn = integer::make(jval); + algebraic_g jdn = integer::make(jdn_day); + + csecs += jdn_fraction_of_day; if (csecs) { algebraic_g frac = +fraction::make(integer::make(csecs), @@ -227,27 +232,20 @@ algebraic_p julian_day_number(algebraic_p dtobj, bool error) } -ularge julian_day_number(int d, int m, int y) +double julian_day_number(int d, int m, int y) // ---------------------------------------------------------------------------- // Compute the Julian day number given day, month and year // ---------------------------------------------------------------------------- -// The algorithm below follows the description in -// https://en.wikipedia.org/wiki/Julian_day#Converting_Gregorian_calendar_date_to_Julian_day_number -// which itself seems to be based on the "Fliegel and van Flandern" algorithms: -// https://aa.usno.navy.mil/faq/JD_formula --> JD. -// With a little bit of algebra this function can be shown to be equivalent. -// -// According to https://en.wikipedia.org/wiki/Gregorian_calendar -// "Thursday 4 October 1582 was followed by Friday 15 October 1582" -// This function doesn't do the 10 day advance. -{ - int rm = (m-14)/12; - ularge jdn = ((1461 * (y + 4800 + rm)) / 4 - + (367 * (m - 2 - 12 * rm)) / 12 - - (3 * ((y + 4900 + rm) / 100)) / 4 - + d - - 32075); - return jdn; +{ + int result; + double djm0, djm; + + result = iauCal2jd(y, m, d, &djm0, &djm); + if (result < 0) + { + // ToDo: handle errors. + } + return (djm0 + djm); } @@ -255,63 +253,63 @@ algebraic_p date_from_julian_day(object_p jdn, bool error) // ---------------------------------------------------------------------------- // Create a date from a Julian day object // ---------------------------------------------------------------------------- -// See comments in julian_day_number { if (!jdn) return nullptr; if (algebraic_g jval = jdn->as_real()) { - large jdn = jval->as_int64(0, error); + double dj1, dj2 = 0.0; + int year, month, day; + double jdn_fraction_of_day; + int result; - enum + // How on earth do I get the real or double value out of jval? { - y = 4716, - j = 1401, - m = 2, - n = 12, - r = 4, - p = 1461, - v = 3, - u = 5, - s = 153, - w = 2, - B = 274277, - C = -38 - }; - - large f = jdn + j + (((4 * jdn + B) / 146097) * 3) / 4 + C; - large e = r * f + v; - large g = (e % p) / r; - large h = u * g + w; - uint day = (h % s) / u + 1; - uint month = (h / s + m ) % n + 1; - int year = e / p - y + (n + m - month) / n; - - bool negativeYear = year < 0; - if (negativeYear) + // Format hhmmsscc, thus cc is hundreds of a second. + const long scale_to_cc = 100 * 100 * 100 * 100; + algebraic_g scale = integer::make(scale_to_cc); + algebraic_g j = jval * scale; + dj1 = double(j->as_uint64(0, false)) / scale_to_cc; + } + + result = iauJd2cal(dj1, dj2, &year, &month, &day, &jdn_fraction_of_day); + if (result < 0) + { + // ToDo: handle errors. + } + + bool negative_year = year < 0; + if (negative_year) year = -year; - ularge dval = year * 10000 + month * 100 + day; + algebraic_g date_part = nullptr; + { + int date = (((year * 100) + month) * 100) + day; + date_part = integer::make(date); + } - algebraic_g date = integer::make(dval); - algebraic_g fp = integer::make(1); - fp = jval % fp; - if (!fp->is_zero()) + algebraic_g time_part = nullptr; { - algebraic_g factor = integer::make(86400); - fp = fp * factor; - ularge hval = fp->as_uint64(0, false); - uint hour = hval / 3600; - uint min = (hval / 60) % 60; - uint sec = hval % 60; - hval = hour * 10000 + min * 100 + sec; - fp = +fraction::make(integer::make(hval), - integer::make(1000000)); - date = date + fp; + const long scale_to_cc = 24 * 60 * 60 * 100; + const long scale_from_cc = 100 * 100 * 100 * 100; + int d = round(jdn_fraction_of_day * scale_to_cc); + int cc = d % 100; + d = d / 100; + int seconds = d % 60; + d = d / 60; + int minutes = d % 60; + d = d / 60; + int hours = d % 24; + + int time = ((hours * 100 + minutes) * 100 + seconds) * 100 + cc; + time_part = +fraction::make(integer::make(time), + +integer::make(scale_from_cc)); } - if (negativeYear) + algebraic_g date = date_part + time_part; + + if (negative_year) date = -date; date = unit::make(date, +symbol::make("date")); @@ -498,9 +496,6 @@ COMMAND_BODY(ChronoTime) } - - - static bool setTime(object_p tobj) // ---------------------------------------------------------------------------- // Set the system date based on input @@ -529,7 +524,6 @@ COMMAND_BODY(SetTime) } - void render_time(renderer &r, algebraic_g &value, cstring hrs, cstring min, cstring sec, uint base, bool ampm) @@ -610,8 +604,8 @@ size_t render_date(renderer &r, algebraic_g date) if (!date || !date->is_real()) return 0; - bool negativeDate = date->is_negative(); - if (negativeDate) + bool negative_date = date->is_negative(); + if (negative_date) date = -date; algebraic_g factor = integer::make(100); @@ -628,9 +622,9 @@ size_t render_date(renderer &r, algebraic_g date) if (Settings.ShowDayOfWeek()) { - int syear = negativeDate ? -int(year) : year; + int syear = negative_date ? -int(year) : year; ularge jdn = julian_day_number(day, month, syear); - uint dow = jdn % 7; + uint dow = (jdn + 1) % 7; r.printf("%s ", get_wday_shortcut(dow)); } @@ -640,10 +634,10 @@ size_t render_date(renderer &r, algebraic_g date) else snprintf(mname, 4, "%u", month); - bool zeroYear = year == 0; - if ((negativeDate || zeroYear) && Settings.BCECEyearNumbering()) + bool zero_year = year == 0; + if ((negative_date || zero_year) && Settings.BCECEyearNumbering()) year = year + 1; - if (negativeDate && Settings.AstronomicalYearNumbering()) + if (negative_date && Settings.AstronomicalYearNumbering()) year = - year; char ytext[16]; @@ -664,7 +658,7 @@ size_t render_date(renderer &r, algebraic_g date) if (Settings.BCECEyearNumbering()) { r.printf(" "); - if (negativeDate || zeroYear) + if (negative_date || zero_year) r.printf("B"); r.printf("CE"); } @@ -680,7 +674,6 @@ size_t render_date(renderer &r, algebraic_g date) } - // ============================================================================ // // HMS and DMS commands @@ -1001,3 +994,466 @@ COMMAND_BODY(TimedEval) return OK; return ERROR; } + + +// **************************************************************************** +// Functions: +// iauCal2jd +// iauJd2cal +// +// Taken from the Standards Of Fundamental Astronomy (SOFA) Libraries, +// issue 2023-10-11. +// +// Inserted jd2cal.c +// Commented out some includes. +// +// Inserted cal2jd.c +// Commented out its includes. +// +// **************************************************************************** + +// #include "sofa.h" +// #include "sofam.h" +#include + +int iauJd2cal(double dj1, double dj2, + int *iy, int *im, int *id, double *fd) +/* +** - - - - - - - - - - +** i a u J d 2 c a l +** - - - - - - - - - - +** +** Julian Date to Gregorian year, month, day, and fraction of a day. +** +** This function is part of the International Astronomical Union's +** SOFA (Standards of Fundamental Astronomy) software collection. +** +** Status: support function. +** +** Given: +** dj1,dj2 double Julian Date (Notes 1, 2) +** +** Returned (arguments): +** iy int year +** im int month +** id int day +** fd double fraction of day +** +** Returned (function value): +** int status: +** 0 = OK +** -1 = unacceptable date (Note 1) +** +** Notes: +** +** 1) The earliest valid date is -68569.5 (-4900 March 1). The +** largest value accepted is 1e9. +** +** 2) The Julian Date is apportioned in any convenient way between +** the arguments dj1 and dj2. For example, JD=2450123.7 could +** be expressed in any of these ways, among others: +** +** dj1 dj2 +** +** 2450123.7 0.0 (JD method) +** 2451545.0 -1421.3 (J2000 method) +** 2400000.5 50123.2 (MJD method) +** 2450123.5 0.2 (date & time method) +** +** Separating integer and fraction uses the "compensated summation" +** algorithm of Kahan-Neumaier to preserve as much precision as +** possible irrespective of the jd1+jd2 apportionment. +** +** 3) In early eras the conversion is from the "proleptic Gregorian +** calendar"; no account is taken of the date(s) of adoption of +** the Gregorian calendar, nor is the AD/BC numbering convention +** observed. +** +** References: +** +** Explanatory Supplement to the Astronomical Almanac, +** P. Kenneth Seidelmann (ed), University Science Books (1992), +** Section 12.92 (p604). +** +** Klein, A., A Generalized Kahan-Babuska-Summation-Algorithm. +** Computing, 76, 279-293 (2006), Section 3. +** +** This revision: 2021 May 11 +** +** SOFA release 2023-10-11 +** +** Copyright (C) 2023 IAU SOFA Board. See notes at end. +*/ +{ +/* Minimum and maximum allowed JD */ + const double DJMIN = -68569.5; + const double DJMAX = 1e9; + + long jd, i, l, n, k; + double dj, f1, f2, d, s, cs, v[2], x, t, f; + + +/* Verify date is acceptable. */ + dj = dj1 + dj2; + if (dj < DJMIN || dj > DJMAX) return -1; + +/* Separate day and fraction (where -0.5 <= fraction < 0.5). */ + d = dnint(dj1); + f1 = dj1 - d; + jd = (long) d; + d = dnint(dj2); + f2 = dj2 - d; + jd += (long) d; + +/* Compute f1+f2+0.5 using compensated summation (Klein 2006). */ + s = 0.5; + cs = 0.0; + v[0] = f1; + v[1] = f2; + for ( i = 0; i < 2; i++ ) { + x = v[i]; + t = s + x; + cs += fabs(s) >= fabs(x) ? (s-t) + x : (x-t) + s; + s = t; + if ( s >= 1.0 ) { + jd++; + s -= 1.0; + } + } + f = s + cs; + cs = f - s; + +/* Deal with negative f. */ + if ( f < 0.0 ) { + + /* Compensated summation: assume that |s| <= 1.0. */ + f = s + 1.0; + cs += (1.0-f) + s; + s = f; + f = s + cs; + cs = f - s; + jd--; + } + +/* Deal with f that is 1.0 or more (when rounded to double). */ + if ( (f-1.0) >= -DBL_EPSILON/4.0 ) { + + /* Compensated summation: assume that |s| <= 1.0. */ + t = s - 1.0; + cs += (s-t) - 1.0; + s = t; + f = s + cs; + if ( -DBL_EPSILON/2.0 < f ) { + jd++; + f = gmax(f, 0.0); + } + } + +/* Express day in Gregorian calendar. */ + l = jd + 68569L; + n = (4L * l) / 146097L; + l -= (146097L * n + 3L) / 4L; + i = (4000L * (l + 1L)) / 1461001L; + l -= (1461L * i) / 4L - 31L; + k = (80L * l) / 2447L; + *id = (int) (l - (2447L * k) / 80L); + l = k / 11L; + *im = (int) (k + 2L - 12L * l); + *iy = (int) (100L * (n - 49L) + i + l); + *fd = f; + +/* Success. */ + return 0; + +/* Finished. */ + +/*---------------------------------------------------------------------- +** +** Copyright (C) 2023 +** Standards of Fundamental Astronomy Board +** of the International Astronomical Union. +** +** ===================== +** SOFA Software License +** ===================== +** +** NOTICE TO USER: +** +** BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND +** CONDITIONS WHICH APPLY TO ITS USE. +** +** 1. The Software is owned by the IAU SOFA Board ("SOFA"). +** +** 2. Permission is granted to anyone to use the SOFA software for any +** purpose, including commercial applications, free of charge and +** without payment of royalties, subject to the conditions and +** restrictions listed below. +** +** 3. You (the user) may copy and distribute SOFA source code to others, +** and use and adapt its code and algorithms in your own software, +** on a world-wide, royalty-free basis. That portion of your +** distribution that does not consist of intact and unchanged copies +** of SOFA source code files is a "derived work" that must comply +** with the following requirements: +** +** a) Your work shall be marked or carry a statement that it +** (i) uses routines and computations derived by you from +** software provided by SOFA under license to you; and +** (ii) does not itself constitute software provided by and/or +** endorsed by SOFA. +** +** b) The source code of your derived work must contain descriptions +** of how the derived work is based upon, contains and/or differs +** from the original SOFA software. +** +** c) The names of all routines in your derived work shall not +** include the prefix "iau" or "sofa" or trivial modifications +** thereof such as changes of case. +** +** d) The origin of the SOFA components of your derived work must +** not be misrepresented; you must not claim that you wrote the +** original software, nor file a patent application for SOFA +** software or algorithms embedded in the SOFA software. +** +** e) These requirements must be reproduced intact in any source +** distribution and shall apply to anyone to whom you have +** granted a further right to modify the source code of your +** derived work. +** +** Note that, as originally distributed, the SOFA software is +** intended to be a definitive implementation of the IAU standards, +** and consequently third-party modifications are discouraged. All +** variations, no matter how minor, must be explicitly marked as +** such, as explained above. +** +** 4. You shall not cause the SOFA software to be brought into +** disrepute, either by misuse, or use for inappropriate tasks, or +** by inappropriate modification. +** +** 5. The SOFA software is provided "as is" and SOFA makes no warranty +** as to its use or performance. SOFA does not and cannot warrant +** the performance or results which the user may obtain by using the +** SOFA software. SOFA makes no warranties, express or implied, as +** to non-infringement of third party rights, merchantability, or +** fitness for any particular purpose. In no event will SOFA be +** liable to the user for any consequential, incidental, or special +** damages, including any lost profits or lost savings, even if a +** SOFA representative has been advised of such damages, or for any +** claim by any third party. +** +** 6. The provision of any version of the SOFA software under the terms +** and conditions specified herein does not imply that future +** versions will also be made available under the same terms and +** conditions. +* +** In any published work or commercial product which uses the SOFA +** software directly, acknowledgement (see www.iausofa.org) is +** appreciated. +** +** Correspondence concerning SOFA software should be addressed as +** follows: +** +** By email: sofa@ukho.gov.uk +** By post: IAU SOFA Center +** HM Nautical Almanac Office +** UK Hydrographic Office +** Admiralty Way, Taunton +** Somerset, TA1 2DN +** United Kingdom +** +**--------------------------------------------------------------------*/ +} + +// **************************************************************************** +// #include "sofa.h" +// #include "sofam.h" + +int iauCal2jd(int iy, int im, int id, double *djm0, double *djm) +/* +** - - - - - - - - - - +** i a u C a l 2 j d +** - - - - - - - - - - +** +** Gregorian Calendar to Julian Date. +** +** This function is part of the International Astronomical Union's +** SOFA (Standards of Fundamental Astronomy) software collection. +** +** Status: support function. +** +** Given: +** iy,im,id int year, month, day in Gregorian calendar (Note 1) +** +** Returned: +** djm0 double MJD zero-point: always 2400000.5 +** djm double Modified Julian Date for 0 hrs +** +** Returned (function value): +** int status: +** 0 = OK +** -1 = bad year (Note 3: JD not computed) +** -2 = bad month (JD not computed) +** -3 = bad day (JD computed) +** +** Notes: +** +** 1) The algorithm used is valid from -4800 March 1, but this +** implementation rejects dates before -4799 January 1. +** +** 2) The Julian Date is returned in two pieces, in the usual SOFA +** manner, which is designed to preserve time resolution. The +** Julian Date is available as a single number by adding djm0 and +** djm. +** +** 3) In early eras the conversion is from the "Proleptic Gregorian +** Calendar"; no account is taken of the date(s) of adoption of +** the Gregorian Calendar, nor is the AD/BC numbering convention +** observed. +** +** Reference: +** +** Explanatory Supplement to the Astronomical Almanac, +** P. Kenneth Seidelmann (ed), University Science Books (1992), +** Section 12.92 (p604). +** +** This revision: 2021 May 11 +** +** SOFA release 2023-10-11 +** +** Copyright (C) 2023 IAU SOFA Board. See notes at end. +*/ +{ + int j, ly, my; + long iypmy; + +/* Earliest year allowed (4800BC) */ + const int IYMIN = -4799; + +/* Month lengths in days */ + static const int mtab[] + = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + +/* Preset status. */ + j = 0; + +/* Validate year and month. */ + if (iy < IYMIN) return -1; + if (im < 1 || im > 12) return -2; + +/* If February in a leap year, 1, otherwise 0. */ + ly = ((im == 2) && !(iy%4) && (iy%100 || !(iy%400))); + +/* Validate day, taking into account leap years. */ + if ( (id < 1) || (id > (mtab[im-1] + ly))) j = -3; + +/* Return result. */ + my = (im - 14) / 12; + iypmy = (long) (iy + my); + *djm0 = DJM0; + *djm = (double)((1461L * (iypmy + 4800L)) / 4L + + (367L * (long) (im - 2 - 12 * my)) / 12L + - (3L * ((iypmy + 4900L) / 100L)) / 4L + + (long) id - 2432076L); + +/* Return status. */ + return j; + +/* Finished. */ + +/*---------------------------------------------------------------------- +** +** Copyright (C) 2023 +** Standards of Fundamental Astronomy Board +** of the International Astronomical Union. +** +** ===================== +** SOFA Software License +** ===================== +** +** NOTICE TO USER: +** +** BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND +** CONDITIONS WHICH APPLY TO ITS USE. +** +** 1. The Software is owned by the IAU SOFA Board ("SOFA"). +** +** 2. Permission is granted to anyone to use the SOFA software for any +** purpose, including commercial applications, free of charge and +** without payment of royalties, subject to the conditions and +** restrictions listed below. +** +** 3. You (the user) may copy and distribute SOFA source code to others, +** and use and adapt its code and algorithms in your own software, +** on a world-wide, royalty-free basis. That portion of your +** distribution that does not consist of intact and unchanged copies +** of SOFA source code files is a "derived work" that must comply +** with the following requirements: +** +** a) Your work shall be marked or carry a statement that it +** (i) uses routines and computations derived by you from +** software provided by SOFA under license to you; and +** (ii) does not itself constitute software provided by and/or +** endorsed by SOFA. +** +** b) The source code of your derived work must contain descriptions +** of how the derived work is based upon, contains and/or differs +** from the original SOFA software. +** +** c) The names of all routines in your derived work shall not +** include the prefix "iau" or "sofa" or trivial modifications +** thereof such as changes of case. +** +** d) The origin of the SOFA components of your derived work must +** not be misrepresented; you must not claim that you wrote the +** original software, nor file a patent application for SOFA +** software or algorithms embedded in the SOFA software. +** +** e) These requirements must be reproduced intact in any source +** distribution and shall apply to anyone to whom you have +** granted a further right to modify the source code of your +** derived work. +** +** Note that, as originally distributed, the SOFA software is +** intended to be a definitive implementation of the IAU standards, +** and consequently third-party modifications are discouraged. All +** variations, no matter how minor, must be explicitly marked as +** such, as explained above. +** +** 4. You shall not cause the SOFA software to be brought into +** disrepute, either by misuse, or use for inappropriate tasks, or +** by inappropriate modification. +** +** 5. The SOFA software is provided "as is" and SOFA makes no warranty +** as to its use or performance. SOFA does not and cannot warrant +** the performance or results which the user may obtain by using the +** SOFA software. SOFA makes no warranties, express or implied, as +** to non-infringement of third party rights, merchantability, or +** fitness for any particular purpose. In no event will SOFA be +** liable to the user for any consequential, incidental, or special +** damages, including any lost profits or lost savings, even if a +** SOFA representative has been advised of such damages, or for any +** claim by any third party. +** +** 6. The provision of any version of the SOFA software under the terms +** and conditions specified herein does not imply that future +** versions will also be made available under the same terms and +** conditions. +* +** In any published work or commercial product which uses the SOFA +** software directly, acknowledgement (see www.iausofa.org) is +** appreciated. +** +** Correspondence concerning SOFA software should be addressed as +** follows: +** +** By email: sofa@ukho.gov.uk +** By post: IAU SOFA Center +** HM Nautical Almanac Office +** UK Hydrographic Office +** Admiralty Way, Taunton +** Somerset, TA1 2DN +** United Kingdom +** +**--------------------------------------------------------------------*/ +} diff --git a/src/datetime.h b/src/datetime.h index dd97dc9a4..5e6bfeecc 100644 --- a/src/datetime.h +++ b/src/datetime.h @@ -42,7 +42,7 @@ algebraic_p to_days(object_p days, bool error = true); // Convert date value to Julian day number, or 0 if fails algebraic_p julian_day_number(algebraic_p date, bool error = true); -ularge julian_day_number(int d, int m, int y); +double julian_day_number(int d, int m, int y); // Convert Julian day number to date algebraic_p date_from_julian_day(object_p jdn, bool error = true); @@ -99,4 +99,28 @@ COMMAND_DECLARE(JulianDayNumber,1);// Return JDN for given date COMMAND_DECLARE(DateFromJulianDayNumber,1); // Date from JDN COMMAND_DECLARE(InsertHms,-1); // Insert _hms, optionnaly replacing _dms + +// **************************************************************************** +// Minimal needed stuff taken from: +// sofam.h +// +// of the Standards Of Fundamental Astronomy (SOFA) Libraries, +// issue 2023-10-11. + +/* dnint(A) - round to nearest whole number (double) */ +#define dnint(A) (fabs(A)<0.5?0.0\ + :((A)<0.0?ceil((A)-0.5):floor((A)+0.5))) + +/* max(A,B) - larger (most +ve) of two numbers (generic) */ +#define gmax(A,B) (((A)>(B))?(A):(B)) + +/* Julian Date of Modified Julian Date zero */ +#define DJM0 (2400000.5) + + +int iauCal2jd(int iy, int im, int id, double *djm0, double *djm); +int iauJd2cal(double dj1, double dj2, + int *iy, int *im, int *id, double *fd); +// **************************************************************************** + #endif // DATETIME_H diff --git a/src/tests.cc b/src/tests.cc index b06f69407..8721b00d4 100644 --- a/src/tests.cc +++ b/src/tests.cc @@ -10079,7 +10079,7 @@ void tests::date_operations() .expect("Mon 17/Feb/1969, 3:55:01.97"); step("Displaying invalid date and time") .test(CLEAR, "999999999.99999999_date", ENTER) - .expect("Sat 99/99/99999, 99:99:99.99"); + .expect("Tue 99/99/99999, 99:99:99.99"); step("Difference between two dates using DDays") .test(CLEAR, "20230908", ENTER) @@ -10131,13 +10131,13 @@ void tests::date_operations() step("Converting from a date to a Julian day number") .test(CLEAR, "20250919_date", ENTER, ID_JulianDayNumber) - .expect("2 460 938"); + .expect("2 460 937 ¹/₂"); step("Converting from a Julian day number to a date") .test(CLEAR, "1 000 000", ENTER, ID_DateFromJulianDayNumber) - .expect("Tue 21/Oct/-1975"); + .expect("Tue 21/Oct/-1975, 12:00:00"); step("Change to BCECE representation") .test(ID_BCECEyearNumbering) - .expect("Tue 21/Oct/1976 BCE"); + .expect("Tue 21/Oct/1976 BCE, 12:00:00"); step("Adding invalid dates") .test(CLEAR, "1 2 DATE+", ENTER) .error("Invalid date"); From cafb1ba996a34be1785f0f4f057d7f36e64ffeb0 Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Tue, 23 Dec 2025 11:45:05 +0100 Subject: [PATCH 12/16] src: comply with SOFA Copyright and license Before I inserted SOFA source code into src/datetime.* because I could not get make to pick up additional files. I found, at least for the simulator, a workaround, by changing sim/db48x.pro. Note: it isn't fixed for other builds. It should be solved by adding the files to the Makefile but I could not get that to work. This commit adds: - src/cal2jd.c - src/jd2cal.c - src/sofa.h - src/sofam.h They are "intact and unchanged copies of SOFA source code files" not "derived work". The previously SOFA source code inserted in src/datetime.* is removed. Only a #include of the SOFA header files is inserted. With this approach I believe to comply with SOFA Copyright and license. ToDo: fix the Makefile or/and other build files. At the moment that is beyond my competence. @c3d please look into this. Signed-off-by: Ed@vanGasteren.net --- sim/db48x.pro | 4 +- src/cal2jd.c | 192 +++++++++++++++ src/datetime.cc | 465 +---------------------------------- src/datetime.h | 24 -- src/jd2cal.c | 251 +++++++++++++++++++ src/sofa.h | 627 ++++++++++++++++++++++++++++++++++++++++++++++++ src/sofam.h | 222 +++++++++++++++++ 7 files changed, 1297 insertions(+), 488 deletions(-) create mode 100644 src/cal2jd.c create mode 100644 src/jd2cal.c create mode 100644 src/sofa.h create mode 100644 src/sofam.h diff --git a/sim/db48x.pro b/sim/db48x.pro index 7ef394655..4910104cf 100644 --- a/sim/db48x.pro +++ b/sim/db48x.pro @@ -92,7 +92,9 @@ SOURCES += \ ../src/unit.cc \ ../src/user_interface.cc \ ../src/util.cc \ - ../src/variables.cc + ../src/variables.cc \ + ../src/jd2cal.c \ + ../src/cal2jd.c HEADERS += \ sim-window.h \ diff --git a/src/cal2jd.c b/src/cal2jd.c new file mode 100644 index 000000000..a0411807f --- /dev/null +++ b/src/cal2jd.c @@ -0,0 +1,192 @@ +#include "sofa.h" +#include "sofam.h" + +int iauCal2jd(int iy, int im, int id, double *djm0, double *djm) +/* +** - - - - - - - - - - +** i a u C a l 2 j d +** - - - - - - - - - - +** +** Gregorian Calendar to Julian Date. +** +** This function is part of the International Astronomical Union's +** SOFA (Standards of Fundamental Astronomy) software collection. +** +** Status: support function. +** +** Given: +** iy,im,id int year, month, day in Gregorian calendar (Note 1) +** +** Returned: +** djm0 double MJD zero-point: always 2400000.5 +** djm double Modified Julian Date for 0 hrs +** +** Returned (function value): +** int status: +** 0 = OK +** -1 = bad year (Note 3: JD not computed) +** -2 = bad month (JD not computed) +** -3 = bad day (JD computed) +** +** Notes: +** +** 1) The algorithm used is valid from -4800 March 1, but this +** implementation rejects dates before -4799 January 1. +** +** 2) The Julian Date is returned in two pieces, in the usual SOFA +** manner, which is designed to preserve time resolution. The +** Julian Date is available as a single number by adding djm0 and +** djm. +** +** 3) In early eras the conversion is from the "Proleptic Gregorian +** Calendar"; no account is taken of the date(s) of adoption of +** the Gregorian Calendar, nor is the AD/BC numbering convention +** observed. +** +** Reference: +** +** Explanatory Supplement to the Astronomical Almanac, +** P. Kenneth Seidelmann (ed), University Science Books (1992), +** Section 12.92 (p604). +** +** This revision: 2021 May 11 +** +** SOFA release 2023-10-11 +** +** Copyright (C) 2023 IAU SOFA Board. See notes at end. +*/ +{ + int j, ly, my; + long iypmy; + +/* Earliest year allowed (4800BC) */ + const int IYMIN = -4799; + +/* Month lengths in days */ + static const int mtab[] + = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + +/* Preset status. */ + j = 0; + +/* Validate year and month. */ + if (iy < IYMIN) return -1; + if (im < 1 || im > 12) return -2; + +/* If February in a leap year, 1, otherwise 0. */ + ly = ((im == 2) && !(iy%4) && (iy%100 || !(iy%400))); + +/* Validate day, taking into account leap years. */ + if ( (id < 1) || (id > (mtab[im-1] + ly))) j = -3; + +/* Return result. */ + my = (im - 14) / 12; + iypmy = (long) (iy + my); + *djm0 = DJM0; + *djm = (double)((1461L * (iypmy + 4800L)) / 4L + + (367L * (long) (im - 2 - 12 * my)) / 12L + - (3L * ((iypmy + 4900L) / 100L)) / 4L + + (long) id - 2432076L); + +/* Return status. */ + return j; + +/* Finished. */ + +/*---------------------------------------------------------------------- +** +** Copyright (C) 2023 +** Standards of Fundamental Astronomy Board +** of the International Astronomical Union. +** +** ===================== +** SOFA Software License +** ===================== +** +** NOTICE TO USER: +** +** BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND +** CONDITIONS WHICH APPLY TO ITS USE. +** +** 1. The Software is owned by the IAU SOFA Board ("SOFA"). +** +** 2. Permission is granted to anyone to use the SOFA software for any +** purpose, including commercial applications, free of charge and +** without payment of royalties, subject to the conditions and +** restrictions listed below. +** +** 3. You (the user) may copy and distribute SOFA source code to others, +** and use and adapt its code and algorithms in your own software, +** on a world-wide, royalty-free basis. That portion of your +** distribution that does not consist of intact and unchanged copies +** of SOFA source code files is a "derived work" that must comply +** with the following requirements: +** +** a) Your work shall be marked or carry a statement that it +** (i) uses routines and computations derived by you from +** software provided by SOFA under license to you; and +** (ii) does not itself constitute software provided by and/or +** endorsed by SOFA. +** +** b) The source code of your derived work must contain descriptions +** of how the derived work is based upon, contains and/or differs +** from the original SOFA software. +** +** c) The names of all routines in your derived work shall not +** include the prefix "iau" or "sofa" or trivial modifications +** thereof such as changes of case. +** +** d) The origin of the SOFA components of your derived work must +** not be misrepresented; you must not claim that you wrote the +** original software, nor file a patent application for SOFA +** software or algorithms embedded in the SOFA software. +** +** e) These requirements must be reproduced intact in any source +** distribution and shall apply to anyone to whom you have +** granted a further right to modify the source code of your +** derived work. +** +** Note that, as originally distributed, the SOFA software is +** intended to be a definitive implementation of the IAU standards, +** and consequently third-party modifications are discouraged. All +** variations, no matter how minor, must be explicitly marked as +** such, as explained above. +** +** 4. You shall not cause the SOFA software to be brought into +** disrepute, either by misuse, or use for inappropriate tasks, or +** by inappropriate modification. +** +** 5. The SOFA software is provided "as is" and SOFA makes no warranty +** as to its use or performance. SOFA does not and cannot warrant +** the performance or results which the user may obtain by using the +** SOFA software. SOFA makes no warranties, express or implied, as +** to non-infringement of third party rights, merchantability, or +** fitness for any particular purpose. In no event will SOFA be +** liable to the user for any consequential, incidental, or special +** damages, including any lost profits or lost savings, even if a +** SOFA representative has been advised of such damages, or for any +** claim by any third party. +** +** 6. The provision of any version of the SOFA software under the terms +** and conditions specified herein does not imply that future +** versions will also be made available under the same terms and +** conditions. +* +** In any published work or commercial product which uses the SOFA +** software directly, acknowledgement (see www.iausofa.org) is +** appreciated. +** +** Correspondence concerning SOFA software should be addressed as +** follows: +** +** By email: sofa@ukho.gov.uk +** By post: IAU SOFA Center +** HM Nautical Almanac Office +** UK Hydrographic Office +** Admiralty Way, Taunton +** Somerset, TA1 2DN +** United Kingdom +** +**--------------------------------------------------------------------*/ +} diff --git a/src/datetime.cc b/src/datetime.cc index 21e6fa89d..718cfba5f 100644 --- a/src/datetime.cc +++ b/src/datetime.cc @@ -36,6 +36,8 @@ #include "tag.h" #include "unit.h" +#include "sofa.h" +#include "sofam.h" // ============================================================================ // @@ -994,466 +996,3 @@ COMMAND_BODY(TimedEval) return OK; return ERROR; } - - -// **************************************************************************** -// Functions: -// iauCal2jd -// iauJd2cal -// -// Taken from the Standards Of Fundamental Astronomy (SOFA) Libraries, -// issue 2023-10-11. -// -// Inserted jd2cal.c -// Commented out some includes. -// -// Inserted cal2jd.c -// Commented out its includes. -// -// **************************************************************************** - -// #include "sofa.h" -// #include "sofam.h" -#include - -int iauJd2cal(double dj1, double dj2, - int *iy, int *im, int *id, double *fd) -/* -** - - - - - - - - - - -** i a u J d 2 c a l -** - - - - - - - - - - -** -** Julian Date to Gregorian year, month, day, and fraction of a day. -** -** This function is part of the International Astronomical Union's -** SOFA (Standards of Fundamental Astronomy) software collection. -** -** Status: support function. -** -** Given: -** dj1,dj2 double Julian Date (Notes 1, 2) -** -** Returned (arguments): -** iy int year -** im int month -** id int day -** fd double fraction of day -** -** Returned (function value): -** int status: -** 0 = OK -** -1 = unacceptable date (Note 1) -** -** Notes: -** -** 1) The earliest valid date is -68569.5 (-4900 March 1). The -** largest value accepted is 1e9. -** -** 2) The Julian Date is apportioned in any convenient way between -** the arguments dj1 and dj2. For example, JD=2450123.7 could -** be expressed in any of these ways, among others: -** -** dj1 dj2 -** -** 2450123.7 0.0 (JD method) -** 2451545.0 -1421.3 (J2000 method) -** 2400000.5 50123.2 (MJD method) -** 2450123.5 0.2 (date & time method) -** -** Separating integer and fraction uses the "compensated summation" -** algorithm of Kahan-Neumaier to preserve as much precision as -** possible irrespective of the jd1+jd2 apportionment. -** -** 3) In early eras the conversion is from the "proleptic Gregorian -** calendar"; no account is taken of the date(s) of adoption of -** the Gregorian calendar, nor is the AD/BC numbering convention -** observed. -** -** References: -** -** Explanatory Supplement to the Astronomical Almanac, -** P. Kenneth Seidelmann (ed), University Science Books (1992), -** Section 12.92 (p604). -** -** Klein, A., A Generalized Kahan-Babuska-Summation-Algorithm. -** Computing, 76, 279-293 (2006), Section 3. -** -** This revision: 2021 May 11 -** -** SOFA release 2023-10-11 -** -** Copyright (C) 2023 IAU SOFA Board. See notes at end. -*/ -{ -/* Minimum and maximum allowed JD */ - const double DJMIN = -68569.5; - const double DJMAX = 1e9; - - long jd, i, l, n, k; - double dj, f1, f2, d, s, cs, v[2], x, t, f; - - -/* Verify date is acceptable. */ - dj = dj1 + dj2; - if (dj < DJMIN || dj > DJMAX) return -1; - -/* Separate day and fraction (where -0.5 <= fraction < 0.5). */ - d = dnint(dj1); - f1 = dj1 - d; - jd = (long) d; - d = dnint(dj2); - f2 = dj2 - d; - jd += (long) d; - -/* Compute f1+f2+0.5 using compensated summation (Klein 2006). */ - s = 0.5; - cs = 0.0; - v[0] = f1; - v[1] = f2; - for ( i = 0; i < 2; i++ ) { - x = v[i]; - t = s + x; - cs += fabs(s) >= fabs(x) ? (s-t) + x : (x-t) + s; - s = t; - if ( s >= 1.0 ) { - jd++; - s -= 1.0; - } - } - f = s + cs; - cs = f - s; - -/* Deal with negative f. */ - if ( f < 0.0 ) { - - /* Compensated summation: assume that |s| <= 1.0. */ - f = s + 1.0; - cs += (1.0-f) + s; - s = f; - f = s + cs; - cs = f - s; - jd--; - } - -/* Deal with f that is 1.0 or more (when rounded to double). */ - if ( (f-1.0) >= -DBL_EPSILON/4.0 ) { - - /* Compensated summation: assume that |s| <= 1.0. */ - t = s - 1.0; - cs += (s-t) - 1.0; - s = t; - f = s + cs; - if ( -DBL_EPSILON/2.0 < f ) { - jd++; - f = gmax(f, 0.0); - } - } - -/* Express day in Gregorian calendar. */ - l = jd + 68569L; - n = (4L * l) / 146097L; - l -= (146097L * n + 3L) / 4L; - i = (4000L * (l + 1L)) / 1461001L; - l -= (1461L * i) / 4L - 31L; - k = (80L * l) / 2447L; - *id = (int) (l - (2447L * k) / 80L); - l = k / 11L; - *im = (int) (k + 2L - 12L * l); - *iy = (int) (100L * (n - 49L) + i + l); - *fd = f; - -/* Success. */ - return 0; - -/* Finished. */ - -/*---------------------------------------------------------------------- -** -** Copyright (C) 2023 -** Standards of Fundamental Astronomy Board -** of the International Astronomical Union. -** -** ===================== -** SOFA Software License -** ===================== -** -** NOTICE TO USER: -** -** BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND -** CONDITIONS WHICH APPLY TO ITS USE. -** -** 1. The Software is owned by the IAU SOFA Board ("SOFA"). -** -** 2. Permission is granted to anyone to use the SOFA software for any -** purpose, including commercial applications, free of charge and -** without payment of royalties, subject to the conditions and -** restrictions listed below. -** -** 3. You (the user) may copy and distribute SOFA source code to others, -** and use and adapt its code and algorithms in your own software, -** on a world-wide, royalty-free basis. That portion of your -** distribution that does not consist of intact and unchanged copies -** of SOFA source code files is a "derived work" that must comply -** with the following requirements: -** -** a) Your work shall be marked or carry a statement that it -** (i) uses routines and computations derived by you from -** software provided by SOFA under license to you; and -** (ii) does not itself constitute software provided by and/or -** endorsed by SOFA. -** -** b) The source code of your derived work must contain descriptions -** of how the derived work is based upon, contains and/or differs -** from the original SOFA software. -** -** c) The names of all routines in your derived work shall not -** include the prefix "iau" or "sofa" or trivial modifications -** thereof such as changes of case. -** -** d) The origin of the SOFA components of your derived work must -** not be misrepresented; you must not claim that you wrote the -** original software, nor file a patent application for SOFA -** software or algorithms embedded in the SOFA software. -** -** e) These requirements must be reproduced intact in any source -** distribution and shall apply to anyone to whom you have -** granted a further right to modify the source code of your -** derived work. -** -** Note that, as originally distributed, the SOFA software is -** intended to be a definitive implementation of the IAU standards, -** and consequently third-party modifications are discouraged. All -** variations, no matter how minor, must be explicitly marked as -** such, as explained above. -** -** 4. You shall not cause the SOFA software to be brought into -** disrepute, either by misuse, or use for inappropriate tasks, or -** by inappropriate modification. -** -** 5. The SOFA software is provided "as is" and SOFA makes no warranty -** as to its use or performance. SOFA does not and cannot warrant -** the performance or results which the user may obtain by using the -** SOFA software. SOFA makes no warranties, express or implied, as -** to non-infringement of third party rights, merchantability, or -** fitness for any particular purpose. In no event will SOFA be -** liable to the user for any consequential, incidental, or special -** damages, including any lost profits or lost savings, even if a -** SOFA representative has been advised of such damages, or for any -** claim by any third party. -** -** 6. The provision of any version of the SOFA software under the terms -** and conditions specified herein does not imply that future -** versions will also be made available under the same terms and -** conditions. -* -** In any published work or commercial product which uses the SOFA -** software directly, acknowledgement (see www.iausofa.org) is -** appreciated. -** -** Correspondence concerning SOFA software should be addressed as -** follows: -** -** By email: sofa@ukho.gov.uk -** By post: IAU SOFA Center -** HM Nautical Almanac Office -** UK Hydrographic Office -** Admiralty Way, Taunton -** Somerset, TA1 2DN -** United Kingdom -** -**--------------------------------------------------------------------*/ -} - -// **************************************************************************** -// #include "sofa.h" -// #include "sofam.h" - -int iauCal2jd(int iy, int im, int id, double *djm0, double *djm) -/* -** - - - - - - - - - - -** i a u C a l 2 j d -** - - - - - - - - - - -** -** Gregorian Calendar to Julian Date. -** -** This function is part of the International Astronomical Union's -** SOFA (Standards of Fundamental Astronomy) software collection. -** -** Status: support function. -** -** Given: -** iy,im,id int year, month, day in Gregorian calendar (Note 1) -** -** Returned: -** djm0 double MJD zero-point: always 2400000.5 -** djm double Modified Julian Date for 0 hrs -** -** Returned (function value): -** int status: -** 0 = OK -** -1 = bad year (Note 3: JD not computed) -** -2 = bad month (JD not computed) -** -3 = bad day (JD computed) -** -** Notes: -** -** 1) The algorithm used is valid from -4800 March 1, but this -** implementation rejects dates before -4799 January 1. -** -** 2) The Julian Date is returned in two pieces, in the usual SOFA -** manner, which is designed to preserve time resolution. The -** Julian Date is available as a single number by adding djm0 and -** djm. -** -** 3) In early eras the conversion is from the "Proleptic Gregorian -** Calendar"; no account is taken of the date(s) of adoption of -** the Gregorian Calendar, nor is the AD/BC numbering convention -** observed. -** -** Reference: -** -** Explanatory Supplement to the Astronomical Almanac, -** P. Kenneth Seidelmann (ed), University Science Books (1992), -** Section 12.92 (p604). -** -** This revision: 2021 May 11 -** -** SOFA release 2023-10-11 -** -** Copyright (C) 2023 IAU SOFA Board. See notes at end. -*/ -{ - int j, ly, my; - long iypmy; - -/* Earliest year allowed (4800BC) */ - const int IYMIN = -4799; - -/* Month lengths in days */ - static const int mtab[] - = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - - -/* Preset status. */ - j = 0; - -/* Validate year and month. */ - if (iy < IYMIN) return -1; - if (im < 1 || im > 12) return -2; - -/* If February in a leap year, 1, otherwise 0. */ - ly = ((im == 2) && !(iy%4) && (iy%100 || !(iy%400))); - -/* Validate day, taking into account leap years. */ - if ( (id < 1) || (id > (mtab[im-1] + ly))) j = -3; - -/* Return result. */ - my = (im - 14) / 12; - iypmy = (long) (iy + my); - *djm0 = DJM0; - *djm = (double)((1461L * (iypmy + 4800L)) / 4L - + (367L * (long) (im - 2 - 12 * my)) / 12L - - (3L * ((iypmy + 4900L) / 100L)) / 4L - + (long) id - 2432076L); - -/* Return status. */ - return j; - -/* Finished. */ - -/*---------------------------------------------------------------------- -** -** Copyright (C) 2023 -** Standards of Fundamental Astronomy Board -** of the International Astronomical Union. -** -** ===================== -** SOFA Software License -** ===================== -** -** NOTICE TO USER: -** -** BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND -** CONDITIONS WHICH APPLY TO ITS USE. -** -** 1. The Software is owned by the IAU SOFA Board ("SOFA"). -** -** 2. Permission is granted to anyone to use the SOFA software for any -** purpose, including commercial applications, free of charge and -** without payment of royalties, subject to the conditions and -** restrictions listed below. -** -** 3. You (the user) may copy and distribute SOFA source code to others, -** and use and adapt its code and algorithms in your own software, -** on a world-wide, royalty-free basis. That portion of your -** distribution that does not consist of intact and unchanged copies -** of SOFA source code files is a "derived work" that must comply -** with the following requirements: -** -** a) Your work shall be marked or carry a statement that it -** (i) uses routines and computations derived by you from -** software provided by SOFA under license to you; and -** (ii) does not itself constitute software provided by and/or -** endorsed by SOFA. -** -** b) The source code of your derived work must contain descriptions -** of how the derived work is based upon, contains and/or differs -** from the original SOFA software. -** -** c) The names of all routines in your derived work shall not -** include the prefix "iau" or "sofa" or trivial modifications -** thereof such as changes of case. -** -** d) The origin of the SOFA components of your derived work must -** not be misrepresented; you must not claim that you wrote the -** original software, nor file a patent application for SOFA -** software or algorithms embedded in the SOFA software. -** -** e) These requirements must be reproduced intact in any source -** distribution and shall apply to anyone to whom you have -** granted a further right to modify the source code of your -** derived work. -** -** Note that, as originally distributed, the SOFA software is -** intended to be a definitive implementation of the IAU standards, -** and consequently third-party modifications are discouraged. All -** variations, no matter how minor, must be explicitly marked as -** such, as explained above. -** -** 4. You shall not cause the SOFA software to be brought into -** disrepute, either by misuse, or use for inappropriate tasks, or -** by inappropriate modification. -** -** 5. The SOFA software is provided "as is" and SOFA makes no warranty -** as to its use or performance. SOFA does not and cannot warrant -** the performance or results which the user may obtain by using the -** SOFA software. SOFA makes no warranties, express or implied, as -** to non-infringement of third party rights, merchantability, or -** fitness for any particular purpose. In no event will SOFA be -** liable to the user for any consequential, incidental, or special -** damages, including any lost profits or lost savings, even if a -** SOFA representative has been advised of such damages, or for any -** claim by any third party. -** -** 6. The provision of any version of the SOFA software under the terms -** and conditions specified herein does not imply that future -** versions will also be made available under the same terms and -** conditions. -* -** In any published work or commercial product which uses the SOFA -** software directly, acknowledgement (see www.iausofa.org) is -** appreciated. -** -** Correspondence concerning SOFA software should be addressed as -** follows: -** -** By email: sofa@ukho.gov.uk -** By post: IAU SOFA Center -** HM Nautical Almanac Office -** UK Hydrographic Office -** Admiralty Way, Taunton -** Somerset, TA1 2DN -** United Kingdom -** -**--------------------------------------------------------------------*/ -} diff --git a/src/datetime.h b/src/datetime.h index 5e6bfeecc..36a796f83 100644 --- a/src/datetime.h +++ b/src/datetime.h @@ -99,28 +99,4 @@ COMMAND_DECLARE(JulianDayNumber,1);// Return JDN for given date COMMAND_DECLARE(DateFromJulianDayNumber,1); // Date from JDN COMMAND_DECLARE(InsertHms,-1); // Insert _hms, optionnaly replacing _dms - -// **************************************************************************** -// Minimal needed stuff taken from: -// sofam.h -// -// of the Standards Of Fundamental Astronomy (SOFA) Libraries, -// issue 2023-10-11. - -/* dnint(A) - round to nearest whole number (double) */ -#define dnint(A) (fabs(A)<0.5?0.0\ - :((A)<0.0?ceil((A)-0.5):floor((A)+0.5))) - -/* max(A,B) - larger (most +ve) of two numbers (generic) */ -#define gmax(A,B) (((A)>(B))?(A):(B)) - -/* Julian Date of Modified Julian Date zero */ -#define DJM0 (2400000.5) - - -int iauCal2jd(int iy, int im, int id, double *djm0, double *djm); -int iauJd2cal(double dj1, double dj2, - int *iy, int *im, int *id, double *fd); -// **************************************************************************** - #endif // DATETIME_H diff --git a/src/jd2cal.c b/src/jd2cal.c new file mode 100644 index 000000000..036c3cd89 --- /dev/null +++ b/src/jd2cal.c @@ -0,0 +1,251 @@ +#include "sofa.h" +#include "sofam.h" +#include + +int iauJd2cal(double dj1, double dj2, + int *iy, int *im, int *id, double *fd) +/* +** - - - - - - - - - - +** i a u J d 2 c a l +** - - - - - - - - - - +** +** Julian Date to Gregorian year, month, day, and fraction of a day. +** +** This function is part of the International Astronomical Union's +** SOFA (Standards of Fundamental Astronomy) software collection. +** +** Status: support function. +** +** Given: +** dj1,dj2 double Julian Date (Notes 1, 2) +** +** Returned (arguments): +** iy int year +** im int month +** id int day +** fd double fraction of day +** +** Returned (function value): +** int status: +** 0 = OK +** -1 = unacceptable date (Note 1) +** +** Notes: +** +** 1) The earliest valid date is -68569.5 (-4900 March 1). The +** largest value accepted is 1e9. +** +** 2) The Julian Date is apportioned in any convenient way between +** the arguments dj1 and dj2. For example, JD=2450123.7 could +** be expressed in any of these ways, among others: +** +** dj1 dj2 +** +** 2450123.7 0.0 (JD method) +** 2451545.0 -1421.3 (J2000 method) +** 2400000.5 50123.2 (MJD method) +** 2450123.5 0.2 (date & time method) +** +** Separating integer and fraction uses the "compensated summation" +** algorithm of Kahan-Neumaier to preserve as much precision as +** possible irrespective of the jd1+jd2 apportionment. +** +** 3) In early eras the conversion is from the "proleptic Gregorian +** calendar"; no account is taken of the date(s) of adoption of +** the Gregorian calendar, nor is the AD/BC numbering convention +** observed. +** +** References: +** +** Explanatory Supplement to the Astronomical Almanac, +** P. Kenneth Seidelmann (ed), University Science Books (1992), +** Section 12.92 (p604). +** +** Klein, A., A Generalized Kahan-Babuska-Summation-Algorithm. +** Computing, 76, 279-293 (2006), Section 3. +** +** This revision: 2021 May 11 +** +** SOFA release 2023-10-11 +** +** Copyright (C) 2023 IAU SOFA Board. See notes at end. +*/ +{ +/* Minimum and maximum allowed JD */ + const double DJMIN = -68569.5; + const double DJMAX = 1e9; + + long jd, i, l, n, k; + double dj, f1, f2, d, s, cs, v[2], x, t, f; + + +/* Verify date is acceptable. */ + dj = dj1 + dj2; + if (dj < DJMIN || dj > DJMAX) return -1; + +/* Separate day and fraction (where -0.5 <= fraction < 0.5). */ + d = dnint(dj1); + f1 = dj1 - d; + jd = (long) d; + d = dnint(dj2); + f2 = dj2 - d; + jd += (long) d; + +/* Compute f1+f2+0.5 using compensated summation (Klein 2006). */ + s = 0.5; + cs = 0.0; + v[0] = f1; + v[1] = f2; + for ( i = 0; i < 2; i++ ) { + x = v[i]; + t = s + x; + cs += fabs(s) >= fabs(x) ? (s-t) + x : (x-t) + s; + s = t; + if ( s >= 1.0 ) { + jd++; + s -= 1.0; + } + } + f = s + cs; + cs = f - s; + +/* Deal with negative f. */ + if ( f < 0.0 ) { + + /* Compensated summation: assume that |s| <= 1.0. */ + f = s + 1.0; + cs += (1.0-f) + s; + s = f; + f = s + cs; + cs = f - s; + jd--; + } + +/* Deal with f that is 1.0 or more (when rounded to double). */ + if ( (f-1.0) >= -DBL_EPSILON/4.0 ) { + + /* Compensated summation: assume that |s| <= 1.0. */ + t = s - 1.0; + cs += (s-t) - 1.0; + s = t; + f = s + cs; + if ( -DBL_EPSILON/2.0 < f ) { + jd++; + f = gmax(f, 0.0); + } + } + +/* Express day in Gregorian calendar. */ + l = jd + 68569L; + n = (4L * l) / 146097L; + l -= (146097L * n + 3L) / 4L; + i = (4000L * (l + 1L)) / 1461001L; + l -= (1461L * i) / 4L - 31L; + k = (80L * l) / 2447L; + *id = (int) (l - (2447L * k) / 80L); + l = k / 11L; + *im = (int) (k + 2L - 12L * l); + *iy = (int) (100L * (n - 49L) + i + l); + *fd = f; + +/* Success. */ + return 0; + +/* Finished. */ + +/*---------------------------------------------------------------------- +** +** Copyright (C) 2023 +** Standards of Fundamental Astronomy Board +** of the International Astronomical Union. +** +** ===================== +** SOFA Software License +** ===================== +** +** NOTICE TO USER: +** +** BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND +** CONDITIONS WHICH APPLY TO ITS USE. +** +** 1. The Software is owned by the IAU SOFA Board ("SOFA"). +** +** 2. Permission is granted to anyone to use the SOFA software for any +** purpose, including commercial applications, free of charge and +** without payment of royalties, subject to the conditions and +** restrictions listed below. +** +** 3. You (the user) may copy and distribute SOFA source code to others, +** and use and adapt its code and algorithms in your own software, +** on a world-wide, royalty-free basis. That portion of your +** distribution that does not consist of intact and unchanged copies +** of SOFA source code files is a "derived work" that must comply +** with the following requirements: +** +** a) Your work shall be marked or carry a statement that it +** (i) uses routines and computations derived by you from +** software provided by SOFA under license to you; and +** (ii) does not itself constitute software provided by and/or +** endorsed by SOFA. +** +** b) The source code of your derived work must contain descriptions +** of how the derived work is based upon, contains and/or differs +** from the original SOFA software. +** +** c) The names of all routines in your derived work shall not +** include the prefix "iau" or "sofa" or trivial modifications +** thereof such as changes of case. +** +** d) The origin of the SOFA components of your derived work must +** not be misrepresented; you must not claim that you wrote the +** original software, nor file a patent application for SOFA +** software or algorithms embedded in the SOFA software. +** +** e) These requirements must be reproduced intact in any source +** distribution and shall apply to anyone to whom you have +** granted a further right to modify the source code of your +** derived work. +** +** Note that, as originally distributed, the SOFA software is +** intended to be a definitive implementation of the IAU standards, +** and consequently third-party modifications are discouraged. All +** variations, no matter how minor, must be explicitly marked as +** such, as explained above. +** +** 4. You shall not cause the SOFA software to be brought into +** disrepute, either by misuse, or use for inappropriate tasks, or +** by inappropriate modification. +** +** 5. The SOFA software is provided "as is" and SOFA makes no warranty +** as to its use or performance. SOFA does not and cannot warrant +** the performance or results which the user may obtain by using the +** SOFA software. SOFA makes no warranties, express or implied, as +** to non-infringement of third party rights, merchantability, or +** fitness for any particular purpose. In no event will SOFA be +** liable to the user for any consequential, incidental, or special +** damages, including any lost profits or lost savings, even if a +** SOFA representative has been advised of such damages, or for any +** claim by any third party. +** +** 6. The provision of any version of the SOFA software under the terms +** and conditions specified herein does not imply that future +** versions will also be made available under the same terms and +** conditions. +* +** In any published work or commercial product which uses the SOFA +** software directly, acknowledgement (see www.iausofa.org) is +** appreciated. +** +** Correspondence concerning SOFA software should be addressed as +** follows: +** +** By email: sofa@ukho.gov.uk +** By post: IAU SOFA Center +** HM Nautical Almanac Office +** UK Hydrographic Office +** Admiralty Way, Taunton +** Somerset, TA1 2DN +** United Kingdom +** +**--------------------------------------------------------------------*/ +} diff --git a/src/sofa.h b/src/sofa.h new file mode 100644 index 000000000..b397769d3 --- /dev/null +++ b/src/sofa.h @@ -0,0 +1,627 @@ +#ifndef SOFAHDEF +#define SOFAHDEF + +/* +** - - - - - - - +** s o f a . h +** - - - - - - - +** +** Prototype function declarations for SOFA library. +** +** This file is part of the International Astronomical Union's +** SOFA (Standards of Fundamental Astronomy) software collection. +** +** This revision: 2023 April 16 +** +** SOFA release 2023-10-11 +** +** Copyright (C) 2023 IAU SOFA Board. See notes at end. +*/ + +#include "math.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Star-independent astrometry parameters */ +typedef struct { + double pmt; /* PM time interval (SSB, Julian years) */ + double eb[3]; /* SSB to observer (vector, au) */ + double eh[3]; /* Sun to observer (unit vector) */ + double em; /* distance from Sun to observer (au) */ + double v[3]; /* barycentric observer velocity (vector, c) */ + double bm1; /* sqrt(1-|v|^2): reciprocal of Lorenz factor */ + double bpn[3][3]; /* bias-precession-nutation matrix */ + double along; /* longitude + s' + dERA(DUT) (radians) */ + double phi; /* geodetic latitude (radians) */ + double xpl; /* polar motion xp wrt local meridian (radians) */ + double ypl; /* polar motion yp wrt local meridian (radians) */ + double sphi; /* sine of geodetic latitude */ + double cphi; /* cosine of geodetic latitude */ + double diurab; /* magnitude of diurnal aberration vector */ + double eral; /* "local" Earth rotation angle (radians) */ + double refa; /* refraction constant A (radians) */ + double refb; /* refraction constant B (radians) */ +} iauASTROM; +/* (Vectors eb, eh, em and v are all with respect to BCRS axes.) */ + +/* Body parameters for light deflection */ +typedef struct { + double bm; /* mass of the body (solar masses) */ + double dl; /* deflection limiter (radians^2/2) */ + double pv[2][3]; /* barycentric PV of the body (au, au/day) */ +} iauLDBODY; + +/* Astronomy/Calendars */ +int iauCal2jd(int iy, int im, int id, double *djm0, double *djm); +double iauEpb(double dj1, double dj2); +void iauEpb2jd(double epb, double *djm0, double *djm); +double iauEpj(double dj1, double dj2); +void iauEpj2jd(double epj, double *djm0, double *djm); +int iauJd2cal(double dj1, double dj2, + int *iy, int *im, int *id, double *fd); +int iauJdcalf(int ndp, double dj1, double dj2, int iymdf[4]); + +/* Astronomy/Astrometry */ +void iauAb(double pnat[3], double v[3], double s, double bm1, + double ppr[3]); +void iauApcg(double date1, double date2, + double ebpv[2][3], double ehp[3], + iauASTROM *astrom); +void iauApcg13(double date1, double date2, iauASTROM *astrom); +void iauApci(double date1, double date2, + double ebpv[2][3], double ehp[3], + double x, double y, double s, + iauASTROM *astrom); +void iauApci13(double date1, double date2, + iauASTROM *astrom, double *eo); +void iauApco(double date1, double date2, + double ebpv[2][3], double ehp[3], + double x, double y, double s, double theta, + double elong, double phi, double hm, + double xp, double yp, double sp, + double refa, double refb, + iauASTROM *astrom); +int iauApco13(double utc1, double utc2, double dut1, + double elong, double phi, double hm, double xp, double yp, + double phpa, double tc, double rh, double wl, + iauASTROM *astrom, double *eo); +void iauApcs(double date1, double date2, double pv[2][3], + double ebpv[2][3], double ehp[3], + iauASTROM *astrom); +void iauApcs13(double date1, double date2, double pv[2][3], + iauASTROM *astrom); +void iauAper(double theta, iauASTROM *astrom); +void iauAper13(double ut11, double ut12, iauASTROM *astrom); +void iauApio(double sp, double theta, + double elong, double phi, double hm, double xp, double yp, + double refa, double refb, + iauASTROM *astrom); +int iauApio13(double utc1, double utc2, double dut1, + double elong, double phi, double hm, double xp, double yp, + double phpa, double tc, double rh, double wl, + iauASTROM *astrom); +void iauAtcc13(double rc, double dc, + double pr, double pd, double px, double rv, + double date1, double date2, + double *ra, double *da); +void iauAtccq(double rc, double dc, + double pr, double pd, double px, double rv, + iauASTROM *astrom, double *ra, double *da); +void iauAtci13(double rc, double dc, + double pr, double pd, double px, double rv, + double date1, double date2, + double *ri, double *di, double *eo); +void iauAtciq(double rc, double dc, double pr, double pd, + double px, double rv, iauASTROM *astrom, + double *ri, double *di); +void iauAtciqn(double rc, double dc, double pr, double pd, + double px, double rv, iauASTROM *astrom, + int n, iauLDBODY b[], double *ri, double *di); +void iauAtciqz(double rc, double dc, iauASTROM *astrom, + double *ri, double *di); +int iauAtco13(double rc, double dc, + double pr, double pd, double px, double rv, + double utc1, double utc2, double dut1, + double elong, double phi, double hm, double xp, double yp, + double phpa, double tc, double rh, double wl, + double *aob, double *zob, double *hob, + double *dob, double *rob, double *eo); +void iauAtic13(double ri, double di, + double date1, double date2, + double *rc, double *dc, double *eo); +void iauAticq(double ri, double di, iauASTROM *astrom, + double *rc, double *dc); +void iauAticqn(double ri, double di, iauASTROM *astrom, + int n, iauLDBODY b[], double *rc, double *dc); +int iauAtio13(double ri, double di, + double utc1, double utc2, double dut1, + double elong, double phi, double hm, double xp, double yp, + double phpa, double tc, double rh, double wl, + double *aob, double *zob, double *hob, + double *dob, double *rob); +void iauAtioq(double ri, double di, iauASTROM *astrom, + double *aob, double *zob, + double *hob, double *dob, double *rob); +int iauAtoc13(const char *type, double ob1, double ob2, + double utc1, double utc2, double dut1, + double elong, double phi, double hm, double xp, double yp, + double phpa, double tc, double rh, double wl, + double *rc, double *dc); +int iauAtoi13(const char *type, double ob1, double ob2, + double utc1, double utc2, double dut1, + double elong, double phi, double hm, double xp, double yp, + double phpa, double tc, double rh, double wl, + double *ri, double *di); +void iauAtoiq(const char *type, + double ob1, double ob2, iauASTROM *astrom, + double *ri, double *di); +void iauLd(double bm, double p[3], double q[3], double e[3], + double em, double dlim, double p1[3]); +void iauLdn(int n, iauLDBODY b[], double ob[3], double sc[3], + double sn[3]); +void iauLdsun(double p[3], double e[3], double em, double p1[3]); +void iauPmpx(double rc, double dc, double pr, double pd, + double px, double rv, double pmt, double pob[3], + double pco[3]); +int iauPmsafe(double ra1, double dec1, double pmr1, double pmd1, + double px1, double rv1, + double ep1a, double ep1b, double ep2a, double ep2b, + double *ra2, double *dec2, double *pmr2, double *pmd2, + double *px2, double *rv2); +void iauPvtob(double elong, double phi, double height, double xp, + double yp, double sp, double theta, double pv[2][3]); +void iauRefco(double phpa, double tc, double rh, double wl, + double *refa, double *refb); + +/* Astronomy/Ephemerides */ +int iauEpv00(double date1, double date2, + double pvh[2][3], double pvb[2][3]); +void iauMoon98(double date1, double date2, double pv[2][3]); +int iauPlan94(double date1, double date2, int np, double pv[2][3]); + +/* Astronomy/FundamentalArgs */ +double iauFad03(double t); +double iauFae03(double t); +double iauFaf03(double t); +double iauFaju03(double t); +double iauFal03(double t); +double iauFalp03(double t); +double iauFama03(double t); +double iauFame03(double t); +double iauFane03(double t); +double iauFaom03(double t); +double iauFapa03(double t); +double iauFasa03(double t); +double iauFaur03(double t); +double iauFave03(double t); + +/* Astronomy/PrecNutPolar */ +void iauBi00(double *dpsibi, double *depsbi, double *dra); +void iauBp00(double date1, double date2, + double rb[3][3], double rp[3][3], double rbp[3][3]); +void iauBp06(double date1, double date2, + double rb[3][3], double rp[3][3], double rbp[3][3]); +void iauBpn2xy(double rbpn[3][3], double *x, double *y); +void iauC2i00a(double date1, double date2, double rc2i[3][3]); +void iauC2i00b(double date1, double date2, double rc2i[3][3]); +void iauC2i06a(double date1, double date2, double rc2i[3][3]); +void iauC2ibpn(double date1, double date2, double rbpn[3][3], + double rc2i[3][3]); +void iauC2ixy(double date1, double date2, double x, double y, + double rc2i[3][3]); +void iauC2ixys(double x, double y, double s, double rc2i[3][3]); +void iauC2t00a(double tta, double ttb, double uta, double utb, + double xp, double yp, double rc2t[3][3]); +void iauC2t00b(double tta, double ttb, double uta, double utb, + double xp, double yp, double rc2t[3][3]); +void iauC2t06a(double tta, double ttb, double uta, double utb, + double xp, double yp, double rc2t[3][3]); +void iauC2tcio(double rc2i[3][3], double era, double rpom[3][3], + double rc2t[3][3]); +void iauC2teqx(double rbpn[3][3], double gst, double rpom[3][3], + double rc2t[3][3]); +void iauC2tpe(double tta, double ttb, double uta, double utb, + double dpsi, double deps, double xp, double yp, + double rc2t[3][3]); +void iauC2txy(double tta, double ttb, double uta, double utb, + double x, double y, double xp, double yp, + double rc2t[3][3]); +double iauEo06a(double date1, double date2); +double iauEors(double rnpb[3][3], double s); +void iauFw2m(double gamb, double phib, double psi, double eps, + double r[3][3]); +void iauFw2xy(double gamb, double phib, double psi, double eps, + double *x, double *y); +void iauLtp(double epj, double rp[3][3]); +void iauLtpb(double epj, double rpb[3][3]); +void iauLtpecl(double epj, double vec[3]); +void iauLtpequ(double epj, double veq[3]); +void iauNum00a(double date1, double date2, double rmatn[3][3]); +void iauNum00b(double date1, double date2, double rmatn[3][3]); +void iauNum06a(double date1, double date2, double rmatn[3][3]); +void iauNumat(double epsa, double dpsi, double deps, double rmatn[3][3]); +void iauNut00a(double date1, double date2, double *dpsi, double *deps); +void iauNut00b(double date1, double date2, double *dpsi, double *deps); +void iauNut06a(double date1, double date2, double *dpsi, double *deps); +void iauNut80(double date1, double date2, double *dpsi, double *deps); +void iauNutm80(double date1, double date2, double rmatn[3][3]); +double iauObl06(double date1, double date2); +double iauObl80(double date1, double date2); +void iauP06e(double date1, double date2, + double *eps0, double *psia, double *oma, double *bpa, + double *bqa, double *pia, double *bpia, + double *epsa, double *chia, double *za, double *zetaa, + double *thetaa, double *pa, + double *gam, double *phi, double *psi); +void iauPb06(double date1, double date2, + double *bzeta, double *bz, double *btheta); +void iauPfw06(double date1, double date2, + double *gamb, double *phib, double *psib, double *epsa); +void iauPmat00(double date1, double date2, double rbp[3][3]); +void iauPmat06(double date1, double date2, double rbp[3][3]); +void iauPmat76(double date1, double date2, double rmatp[3][3]); +void iauPn00(double date1, double date2, double dpsi, double deps, + double *epsa, + double rb[3][3], double rp[3][3], double rbp[3][3], + double rn[3][3], double rbpn[3][3]); +void iauPn00a(double date1, double date2, + double *dpsi, double *deps, double *epsa, + double rb[3][3], double rp[3][3], double rbp[3][3], + double rn[3][3], double rbpn[3][3]); +void iauPn00b(double date1, double date2, + double *dpsi, double *deps, double *epsa, + double rb[3][3], double rp[3][3], double rbp[3][3], + double rn[3][3], double rbpn[3][3]); +void iauPn06(double date1, double date2, double dpsi, double deps, + double *epsa, + double rb[3][3], double rp[3][3], double rbp[3][3], + double rn[3][3], double rbpn[3][3]); +void iauPn06a(double date1, double date2, + double *dpsi, double *deps, double *epsa, + double rb[3][3], double rp[3][3], double rbp[3][3], + double rn[3][3], double rbpn[3][3]); +void iauPnm00a(double date1, double date2, double rbpn[3][3]); +void iauPnm00b(double date1, double date2, double rbpn[3][3]); +void iauPnm06a(double date1, double date2, double rnpb[3][3]); +void iauPnm80(double date1, double date2, double rmatpn[3][3]); +void iauPom00(double xp, double yp, double sp, double rpom[3][3]); +void iauPr00(double date1, double date2, + double *dpsipr, double *depspr); +void iauPrec76(double date01, double date02, + double date11, double date12, + double *zeta, double *z, double *theta); +double iauS00(double date1, double date2, double x, double y); +double iauS00a(double date1, double date2); +double iauS00b(double date1, double date2); +double iauS06(double date1, double date2, double x, double y); +double iauS06a(double date1, double date2); +double iauSp00(double date1, double date2); +void iauXy06(double date1, double date2, double *x, double *y); +void iauXys00a(double date1, double date2, + double *x, double *y, double *s); +void iauXys00b(double date1, double date2, + double *x, double *y, double *s); +void iauXys06a(double date1, double date2, + double *x, double *y, double *s); + +/* Astronomy/RotationAndTime */ +double iauEe00(double date1, double date2, double epsa, double dpsi); +double iauEe00a(double date1, double date2); +double iauEe00b(double date1, double date2); +double iauEe06a(double date1, double date2); +double iauEect00(double date1, double date2); +double iauEqeq94(double date1, double date2); +double iauEra00(double dj1, double dj2); +double iauGmst00(double uta, double utb, double tta, double ttb); +double iauGmst06(double uta, double utb, double tta, double ttb); +double iauGmst82(double dj1, double dj2); +double iauGst00a(double uta, double utb, double tta, double ttb); +double iauGst00b(double uta, double utb); +double iauGst06(double uta, double utb, double tta, double ttb, + double rnpb[3][3]); +double iauGst06a(double uta, double utb, double tta, double ttb); +double iauGst94(double uta, double utb); + +/* Astronomy/SpaceMotion */ +int iauPvstar(double pv[2][3], double *ra, double *dec, + double *pmr, double *pmd, double *px, double *rv); +int iauStarpv(double ra, double dec, + double pmr, double pmd, double px, double rv, + double pv[2][3]); + +/* Astronomy/StarCatalogs */ +void iauFk425(double r1950, double d1950, + double dr1950, double dd1950, + double p1950, double v1950, + double *r2000, double *d2000, + double *dr2000, double *dd2000, + double *p2000, double *v2000); +void iauFk45z(double r1950, double d1950, double bepoch, + double *r2000, double *d2000); +void iauFk524(double r2000, double d2000, + double dr2000, double dd2000, + double p2000, double v2000, + double *r1950, double *d1950, + double *dr1950, double *dd1950, + double *p1950, double *v1950); +void iauFk52h(double r5, double d5, + double dr5, double dd5, double px5, double rv5, + double *rh, double *dh, + double *drh, double *ddh, double *pxh, double *rvh); +void iauFk54z(double r2000, double d2000, double bepoch, + double *r1950, double *d1950, + double *dr1950, double *dd1950); +void iauFk5hip(double r5h[3][3], double s5h[3]); +void iauFk5hz(double r5, double d5, double date1, double date2, + double *rh, double *dh); +void iauH2fk5(double rh, double dh, + double drh, double ddh, double pxh, double rvh, + double *r5, double *d5, + double *dr5, double *dd5, double *px5, double *rv5); +void iauHfk5z(double rh, double dh, double date1, double date2, + double *r5, double *d5, double *dr5, double *dd5); +int iauStarpm(double ra1, double dec1, + double pmr1, double pmd1, double px1, double rv1, + double ep1a, double ep1b, double ep2a, double ep2b, + double *ra2, double *dec2, + double *pmr2, double *pmd2, double *px2, double *rv2); + +/* Astronomy/EclipticCoordinates */ +void iauEceq06(double date1, double date2, double dl, double db, + double *dr, double *dd); +void iauEcm06(double date1, double date2, double rm[3][3]); +void iauEqec06(double date1, double date2, double dr, double dd, + double *dl, double *db); +void iauLteceq(double epj, double dl, double db, double *dr, double *dd); +void iauLtecm(double epj, double rm[3][3]); +void iauLteqec(double epj, double dr, double dd, double *dl, double *db); + +/* Astronomy/GalacticCoordinates */ +void iauG2icrs(double dl, double db, double *dr, double *dd); +void iauIcrs2g(double dr, double dd, double *dl, double *db); + +/* Astronomy/GeodeticGeocentric */ +int iauEform(int n, double *a, double *f); +int iauGc2gd(int n, double xyz[3], + double *elong, double *phi, double *height); +int iauGc2gde(double a, double f, double xyz[3], + double *elong, double *phi, double *height); +int iauGd2gc(int n, double elong, double phi, double height, + double xyz[3]); +int iauGd2gce(double a, double f, + double elong, double phi, double height, double xyz[3]); + +/* Astronomy/Timescales */ +int iauD2dtf(const char *scale, int ndp, double d1, double d2, + int *iy, int *im, int *id, int ihmsf[4]); +int iauDat(int iy, int im, int id, double fd, double *deltat); +double iauDtdb(double date1, double date2, + double ut, double elong, double u, double v); +int iauDtf2d(const char *scale, int iy, int im, int id, + int ihr, int imn, double sec, double *d1, double *d2); +int iauTaitt(double tai1, double tai2, double *tt1, double *tt2); +int iauTaiut1(double tai1, double tai2, double dta, + double *ut11, double *ut12); +int iauTaiutc(double tai1, double tai2, double *utc1, double *utc2); +int iauTcbtdb(double tcb1, double tcb2, double *tdb1, double *tdb2); +int iauTcgtt(double tcg1, double tcg2, double *tt1, double *tt2); +int iauTdbtcb(double tdb1, double tdb2, double *tcb1, double *tcb2); +int iauTdbtt(double tdb1, double tdb2, double dtr, + double *tt1, double *tt2); +int iauTttai(double tt1, double tt2, double *tai1, double *tai2); +int iauTttcg(double tt1, double tt2, double *tcg1, double *tcg2); +int iauTttdb(double tt1, double tt2, double dtr, + double *tdb1, double *tdb2); +int iauTtut1(double tt1, double tt2, double dt, + double *ut11, double *ut12); +int iauUt1tai(double ut11, double ut12, double dta, + double *tai1, double *tai2); +int iauUt1tt(double ut11, double ut12, double dt, + double *tt1, double *tt2); +int iauUt1utc(double ut11, double ut12, double dut1, + double *utc1, double *utc2); +int iauUtctai(double utc1, double utc2, double *tai1, double *tai2); +int iauUtcut1(double utc1, double utc2, double dut1, + double *ut11, double *ut12); + +/* Astronomy/HorizonEquatorial */ +void iauAe2hd(double az, double el, double phi, + double *ha, double *dec); +void iauHd2ae(double ha, double dec, double phi, + double *az, double *el); +double iauHd2pa(double ha, double dec, double phi); + +/* Astronomy/Gnomonic */ +int iauTpors(double xi, double eta, double a, double b, + double *a01, double *b01, double *a02, double *b02); +int iauTporv(double xi, double eta, double v[3], + double v01[3], double v02[3]); +void iauTpsts(double xi, double eta, double a0, double b0, + double *a, double *b); +void iauTpstv(double xi, double eta, double v0[3], double v[3]); +int iauTpxes(double a, double b, double a0, double b0, + double *xi, double *eta); +int iauTpxev(double v[3], double v0[3], double *xi, double *eta); + +/* VectorMatrix/AngleOps */ +void iauA2af(int ndp, double angle, char *sign, int idmsf[4]); +void iauA2tf(int ndp, double angle, char *sign, int ihmsf[4]); +int iauAf2a(char s, int ideg, int iamin, double asec, double *rad); +double iauAnp(double a); +double iauAnpm(double a); +void iauD2tf(int ndp, double days, char *sign, int ihmsf[4]); +int iauTf2a(char s, int ihour, int imin, double sec, double *rad); +int iauTf2d(char s, int ihour, int imin, double sec, double *days); + +/* VectorMatrix/BuildRotations */ +void iauRx(double phi, double r[3][3]); +void iauRy(double theta, double r[3][3]); +void iauRz(double psi, double r[3][3]); + +/* VectorMatrix/CopyExtendExtract */ +void iauCp(double p[3], double c[3]); +void iauCpv(double pv[2][3], double c[2][3]); +void iauCr(double r[3][3], double c[3][3]); +void iauP2pv(double p[3], double pv[2][3]); +void iauPv2p(double pv[2][3], double p[3]); + +/* VectorMatrix/Initialization */ +void iauIr(double r[3][3]); +void iauZp(double p[3]); +void iauZpv(double pv[2][3]); +void iauZr(double r[3][3]); + +/* VectorMatrix/MatrixOps */ +void iauRxr(double a[3][3], double b[3][3], double atb[3][3]); +void iauTr(double r[3][3], double rt[3][3]); + +/* VectorMatrix/MatrixVectorProducts */ +void iauRxp(double r[3][3], double p[3], double rp[3]); +void iauRxpv(double r[3][3], double pv[2][3], double rpv[2][3]); +void iauTrxp(double r[3][3], double p[3], double trp[3]); +void iauTrxpv(double r[3][3], double pv[2][3], double trpv[2][3]); + +/* VectorMatrix/RotationVectors */ +void iauRm2v(double r[3][3], double w[3]); +void iauRv2m(double w[3], double r[3][3]); + +/* VectorMatrix/SeparationAndAngle */ +double iauPap(double a[3], double b[3]); +double iauPas(double al, double ap, double bl, double bp); +double iauSepp(double a[3], double b[3]); +double iauSeps(double al, double ap, double bl, double bp); + +/* VectorMatrix/SphericalCartesian */ +void iauC2s(double p[3], double *theta, double *phi); +void iauP2s(double p[3], double *theta, double *phi, double *r); +void iauPv2s(double pv[2][3], + double *theta, double *phi, double *r, + double *td, double *pd, double *rd); +void iauS2c(double theta, double phi, double c[3]); +void iauS2p(double theta, double phi, double r, double p[3]); +void iauS2pv(double theta, double phi, double r, + double td, double pd, double rd, + double pv[2][3]); + +/* VectorMatrix/VectorOps */ +double iauPdp(double a[3], double b[3]); +double iauPm(double p[3]); +void iauPmp(double a[3], double b[3], double amb[3]); +void iauPn(double p[3], double *r, double u[3]); +void iauPpp(double a[3], double b[3], double apb[3]); +void iauPpsp(double a[3], double s, double b[3], double apsb[3]); +void iauPvdpv(double a[2][3], double b[2][3], double adb[2]); +void iauPvm(double pv[2][3], double *r, double *s); +void iauPvmpv(double a[2][3], double b[2][3], double amb[2][3]); +void iauPvppv(double a[2][3], double b[2][3], double apb[2][3]); +void iauPvu(double dt, double pv[2][3], double upv[2][3]); +void iauPvup(double dt, double pv[2][3], double p[3]); +void iauPvxpv(double a[2][3], double b[2][3], double axb[2][3]); +void iauPxp(double a[3], double b[3], double axb[3]); +void iauS2xpv(double s1, double s2, double pv[2][3], double spv[2][3]); +void iauSxp(double s, double p[3], double sp[3]); +void iauSxpv(double s, double pv[2][3], double spv[2][3]); + +#ifdef __cplusplus +} +#endif + +#endif + +/*---------------------------------------------------------------------- +** +** Copyright (C) 2023 +** Standards of Fundamental Astronomy Board +** of the International Astronomical Union. +** +** ===================== +** SOFA Software License +** ===================== +** +** NOTICE TO USER: +** +** BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND +** CONDITIONS WHICH APPLY TO ITS USE. +** +** 1. The Software is owned by the IAU SOFA Board ("SOFA"). +** +** 2. Permission is granted to anyone to use the SOFA software for any +** purpose, including commercial applications, free of charge and +** without payment of royalties, subject to the conditions and +** restrictions listed below. +** +** 3. You (the user) may copy and distribute SOFA source code to others, +** and use and adapt its code and algorithms in your own software, +** on a world-wide, royalty-free basis. That portion of your +** distribution that does not consist of intact and unchanged copies +** of SOFA source code files is a "derived work" that must comply +** with the following requirements: +** +** a) Your work shall be marked or carry a statement that it +** (i) uses routines and computations derived by you from +** software provided by SOFA under license to you; and +** (ii) does not itself constitute software provided by and/or +** endorsed by SOFA. +** +** b) The source code of your derived work must contain descriptions +** of how the derived work is based upon, contains and/or differs +** from the original SOFA software. +** +** c) The names of all routines in your derived work shall not +** include the prefix "iau" or "sofa" or trivial modifications +** thereof such as changes of case. +** +** d) The origin of the SOFA components of your derived work must +** not be misrepresented; you must not claim that you wrote the +** original software, nor file a patent application for SOFA +** software or algorithms embedded in the SOFA software. +** +** e) These requirements must be reproduced intact in any source +** distribution and shall apply to anyone to whom you have +** granted a further right to modify the source code of your +** derived work. +** +** Note that, as originally distributed, the SOFA software is +** intended to be a definitive implementation of the IAU standards, +** and consequently third-party modifications are discouraged. All +** variations, no matter how minor, must be explicitly marked as +** such, as explained above. +** +** 4. You shall not cause the SOFA software to be brought into +** disrepute, either by misuse, or use for inappropriate tasks, or +** by inappropriate modification. +** +** 5. The SOFA software is provided "as is" and SOFA makes no warranty +** as to its use or performance. SOFA does not and cannot warrant +** the performance or results which the user may obtain by using the +** SOFA software. SOFA makes no warranties, express or implied, as +** to non-infringement of third party rights, merchantability, or +** fitness for any particular purpose. In no event will SOFA be +** liable to the user for any consequential, incidental, or special +** damages, including any lost profits or lost savings, even if a +** SOFA representative has been advised of such damages, or for any +** claim by any third party. +** +** 6. The provision of any version of the SOFA software under the terms +** and conditions specified herein does not imply that future +** versions will also be made available under the same terms and +** conditions. +* +** In any published work or commercial product which uses the SOFA +** software directly, acknowledgement (see www.iausofa.org) is +** appreciated. +** +** Correspondence concerning SOFA software should be addressed as +** follows: +** +** By email: sofa@ukho.gov.uk +** By post: IAU SOFA Center +** HM Nautical Almanac Office +** UK Hydrographic Office +** Admiralty Way, Taunton +** Somerset, TA1 2DN +** United Kingdom +** +**--------------------------------------------------------------------*/ diff --git a/src/sofam.h b/src/sofam.h new file mode 100644 index 000000000..9279f7277 --- /dev/null +++ b/src/sofam.h @@ -0,0 +1,222 @@ +#ifndef SOFAMHDEF +#define SOFAMHDEF + +/* +** - - - - - - - - +** s o f a m . h +** - - - - - - - - +** +** Macros used by SOFA library. +** +** This file is part of the International Astronomical Union's +** SOFA (Standards of Fundamental Astronomy) software collection. +** +** Please note that the constants defined below are to be used only in +** the context of the SOFA software, and have no other official IAU +** status. In addition, self consistency is not guaranteed. +** +** This revision: 2021 February 24 +** +** SOFA release 2023-10-11 +** +** Copyright (C) 2023 IAU SOFA Board. See notes at end. +*/ + +/* Pi */ +#define DPI (3.141592653589793238462643) + +/* 2Pi */ +#define D2PI (6.283185307179586476925287) + +/* Radians to degrees */ +#define DR2D (57.29577951308232087679815) + +/* Degrees to radians */ +#define DD2R (1.745329251994329576923691e-2) + +/* Radians to arcseconds */ +#define DR2AS (206264.8062470963551564734) + +/* Arcseconds to radians */ +#define DAS2R (4.848136811095359935899141e-6) + +/* Seconds of time to radians */ +#define DS2R (7.272205216643039903848712e-5) + +/* Arcseconds in a full circle */ +#define TURNAS (1296000.0) + +/* Milliarcseconds to radians */ +#define DMAS2R (DAS2R / 1e3) + +/* Length of tropical year B1900 (days) */ +#define DTY (365.242198781) + +/* Seconds per day. */ +#define DAYSEC (86400.0) + +/* Days per Julian year */ +#define DJY (365.25) + +/* Days per Julian century */ +#define DJC (36525.0) + +/* Days per Julian millennium */ +#define DJM (365250.0) + +/* Reference epoch (J2000.0), Julian Date */ +#define DJ00 (2451545.0) + +/* Julian Date of Modified Julian Date zero */ +#define DJM0 (2400000.5) + +/* Reference epoch (J2000.0), Modified Julian Date */ +#define DJM00 (51544.5) + +/* 1977 Jan 1.0 as MJD */ +#define DJM77 (43144.0) + +/* TT minus TAI (s) */ +#define TTMTAI (32.184) + +/* Astronomical unit (m, IAU 2012) */ +#define DAU (149597870.7e3) + +/* Speed of light (m/s) */ +#define CMPS 299792458.0 + +/* Light time for 1 au (s) */ +#define AULT (DAU/CMPS) + +/* Speed of light (au per day) */ +#define DC (DAYSEC/AULT) + +/* L_G = 1 - d(TT)/d(TCG) */ +#define ELG (6.969290134e-10) + +/* L_B = 1 - d(TDB)/d(TCB), and TDB (s) at TAI 1977/1/1.0 */ +#define ELB (1.550519768e-8) +#define TDB0 (-6.55e-5) + +/* Schwarzschild radius of the Sun (au) */ +/* = 2 * 1.32712440041e20 / (2.99792458e8)^2 / 1.49597870700e11 */ +#define SRS 1.97412574336e-8 + +/* dint(A) - truncate to nearest whole number towards zero (double) */ +#define dint(A) ((A)<0.0?ceil(A):floor(A)) + +/* dnint(A) - round to nearest whole number (double) */ +#define dnint(A) (fabs(A)<0.5?0.0\ + :((A)<0.0?ceil((A)-0.5):floor((A)+0.5))) + +/* dsign(A,B) - magnitude of A with sign of B (double) */ +#define dsign(A,B) ((B)<0.0?-fabs(A):fabs(A)) + +/* max(A,B) - larger (most +ve) of two numbers (generic) */ +#define gmax(A,B) (((A)>(B))?(A):(B)) + +/* min(A,B) - smaller (least +ve) of two numbers (generic) */ +#define gmin(A,B) (((A)<(B))?(A):(B)) + +/* Reference ellipsoids */ +#define WGS84 1 +#define GRS80 2 +#define WGS72 3 + +#endif + +/*---------------------------------------------------------------------- +** +** Copyright (C) 2023 +** Standards of Fundamental Astronomy Board +** of the International Astronomical Union. +** +** ===================== +** SOFA Software License +** ===================== +** +** NOTICE TO USER: +** +** BY USING THIS SOFTWARE YOU ACCEPT THE FOLLOWING SIX TERMS AND +** CONDITIONS WHICH APPLY TO ITS USE. +** +** 1. The Software is owned by the IAU SOFA Board ("SOFA"). +** +** 2. Permission is granted to anyone to use the SOFA software for any +** purpose, including commercial applications, free of charge and +** without payment of royalties, subject to the conditions and +** restrictions listed below. +** +** 3. You (the user) may copy and distribute SOFA source code to others, +** and use and adapt its code and algorithms in your own software, +** on a world-wide, royalty-free basis. That portion of your +** distribution that does not consist of intact and unchanged copies +** of SOFA source code files is a "derived work" that must comply +** with the following requirements: +** +** a) Your work shall be marked or carry a statement that it +** (i) uses routines and computations derived by you from +** software provided by SOFA under license to you; and +** (ii) does not itself constitute software provided by and/or +** endorsed by SOFA. +** +** b) The source code of your derived work must contain descriptions +** of how the derived work is based upon, contains and/or differs +** from the original SOFA software. +** +** c) The names of all routines in your derived work shall not +** include the prefix "iau" or "sofa" or trivial modifications +** thereof such as changes of case. +** +** d) The origin of the SOFA components of your derived work must +** not be misrepresented; you must not claim that you wrote the +** original software, nor file a patent application for SOFA +** software or algorithms embedded in the SOFA software. +** +** e) These requirements must be reproduced intact in any source +** distribution and shall apply to anyone to whom you have +** granted a further right to modify the source code of your +** derived work. +** +** Note that, as originally distributed, the SOFA software is +** intended to be a definitive implementation of the IAU standards, +** and consequently third-party modifications are discouraged. All +** variations, no matter how minor, must be explicitly marked as +** such, as explained above. +** +** 4. You shall not cause the SOFA software to be brought into +** disrepute, either by misuse, or use for inappropriate tasks, or +** by inappropriate modification. +** +** 5. The SOFA software is provided "as is" and SOFA makes no warranty +** as to its use or performance. SOFA does not and cannot warrant +** the performance or results which the user may obtain by using the +** SOFA software. SOFA makes no warranties, express or implied, as +** to non-infringement of third party rights, merchantability, or +** fitness for any particular purpose. In no event will SOFA be +** liable to the user for any consequential, incidental, or special +** damages, including any lost profits or lost savings, even if a +** SOFA representative has been advised of such damages, or for any +** claim by any third party. +** +** 6. The provision of any version of the SOFA software under the terms +** and conditions specified herein does not imply that future +** versions will also be made available under the same terms and +** conditions. +* +** In any published work or commercial product which uses the SOFA +** software directly, acknowledgement (see www.iausofa.org) is +** appreciated. +** +** Correspondence concerning SOFA software should be addressed as +** follows: +** +** By email: sofa@ukho.gov.uk +** By post: IAU SOFA Center +** HM Nautical Almanac Office +** UK Hydrographic Office +** Admiralty Way, Taunton +** Somerset, TA1 2DN +** United Kingdom +** +**--------------------------------------------------------------------*/ From 0e86740bcc82078542b3255fad0302a0c21216c2 Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Sat, 27 Dec 2025 18:36:34 +0100 Subject: [PATCH 13/16] doc: Improve Date and Time documentation An other round of making this part of the documentation better (I think). Signed-off-by: Ed@vanGasteren.net --- doc/commands/system.md | 159 +++++++++++++++++++++++++++++++---------- 1 file changed, 121 insertions(+), 38 deletions(-) diff --git a/doc/commands/system.md b/doc/commands/system.md index 854377ebd..cfbeb3ead 100755 --- a/doc/commands/system.md +++ b/doc/commands/system.md @@ -1,9 +1,80 @@ -# Time, Date, Alarms and System Commands +# Date, Time + + +## Date entry / edit format + +A whole number with a `_date` unit attached is interpreted as a date according to the customary format `YYYYMMDD`. +However, the year need not be a 4 digit number. +It can a smaller, bigger, zero, even a negative number and leading zeros can be ommitted +(as such it need not fit the `YYYY` format). +In case of a negative number only the year is treated as such. +Months and days, even in a negative year, run from low (positive numbers) to high within the year. + +Note: the date format is intentionally different from the format on the HP-48. + +Note: not all commands can handle a negative year. +The underlying platform DMCP of the SwissMicros calculators handles only positive years. +That bubbles up to several commands. + + +## Date display format + +By default a Date is displayed on the stack like `Sun 30/Nov/2025`. +The format can be adjusted by changing the [Date, Time flags](#date-time-flags) or +[Date, Time settings](#date-time-settings). + + +## Date+Time entry / edit format + +A real number with a `_date` unit attached is interpreted as a Date + Time +according to the format `YYYYMMDD.HHMMSS`. + + +## Date+Time display format + +By default a Date+Time is displayed on the stack like `Sun 30/Nov/2025, 16:43:10`. +The format can be adjusted by changing the [Date, Time flags](#date-time-flags) or +[Date, Time settings](#date-time-settings). + + +## Time entry format + +Enter the hours, a '.' to end the hours an begin the minutes. +After the minutes enter a second '.' to end the minutes and begin the seconds. +The display will change to `°′_dms`, assuming you are entering an angle. +Proceed with the seconds. +Optionally you can give a third '.' followed by a fraction of a second. +Enter the fraction as numerator '.' (yes, a fourth; not a '/') denominator. +Finally change the unit from `_dms` to `_hms`. +With the cursor positioned before the unit you can just attach the `_hms` unit (it replaces the `_dms`). +Or you can use the `→HMS` command. +That pushes the value on the stack. +Both the `_hms` unit and the `→HMS` command can be found in the [TimeMenu](#timemenu). +Or, in alpha mode, you can change the 'd' in an 'h'. + +A second way to enter a time is as `._hms`. + + +## Time edit format + +In edit mode a time wil show as `HH°MM′SS″_hms`. +A leading zero of the hours will be left out. +If the fraction of a second is zero it will be left out. + + +## Time display format + +On the stack a time wil show as `HH:MM:SS.`. +A leading zero of the hours will be left out. +Note the ':' as separator. +If the fraction of a second is zero the '.' and the fraction will be left out. +The `_hms` unit will not show. + ## DateMenu -Activated from the [Time](#TimeMenu) menu. +Access: [Time](#TimeMenu) menu. Show a softkey menu for date-related commands, including: @@ -15,9 +86,10 @@ Show a softkey menu for date-related commands, including: * `JulianDayNumber` * `DateFromJulianDayNumber` + ## TimeMenu -Activated by the 🟦 _V_ (_TIME_) key. +Access: 🟦 _V_ (_TIME_) key. Show a softkey menu for time-related commands, including: @@ -33,7 +105,8 @@ Show a softkey menu for time-related commands, including: * `TimedEval` * `SetTime` -## Time, Date related flags + +## Date, Time flags * `HideDate` / `ShowDate` * `HideTime` / `ShowTime` @@ -46,54 +119,51 @@ Show a softkey menu for time-related commands, including: * `HideDayOfWeek` / `ShowDayOfWeek` * `BCECEyearNumbering` / `AstronomicalYearNumbering` -## Time, Date related settings + +## Date, Time settings * `DateSlash` / `DateDash` / `DateDot` / `DateSpace` +* `DateSeparatorCommand` + ## BCECEyearNumbering -Activate the B(efore) C(ommon) E(ra) / C(ommon) E(ra) suffix of the year in the display of a date on the stack. -Activate the related year numbering which jumps from 1 BCE to 1 CE. So negative years are shifted. +Access: + +Activate the B(efore) C(ommon) E(ra) / C(ommon) E(ra) year numbering. + +Display years on the stack with a BCE (for negative years) or CE (for positive years) suffix. +This uses a non uniform timeline without a year = 0. +The year numbering jumps from 1 BCE to 1 CE. So negative years are shifted. See: [Proleptic Gregorian calendar](https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar) -## AstronomicalYearNumbering -Activate the Astronomical year numbering. This uses a uniform timeline including a year = 0. -Display negative years on the stack with a minus sign. -See: [Astronomical year numbering](https://en.wikipedia.org/wiki/Astronomical_year_numbering) +## AstronomicalYearNumbering -## Date entry / edit format +Access: -A whole number with a `_date` unit attached is interpreted as a date according to the customary format `YYYYMMDD`. -The year need not be a 4 digit number. -It can a smaller, bigger, zero, even a negative number and leading zeros can be ommitted -(as such it need not fit the `YYYY` format). -In case of a negative number only the year is treated as such. -Months and days, even in a negative year, run from low (positive numbers) to high. +Activate the Astronomical year numbering. -Note: the date format is intentionally different from the format on the HP-48. +Display negative years on the stack with a minus sign. +This uses a uniform timeline including a year = 0. +See: [Astronomical year numbering](https://en.wikipedia.org/wiki/Astronomical_year_numbering) -## Date display format -By default a Date is displayed on the stack like `Sun 30/Nov/2025`. -The format can be adjusted by changing the [Time, Date related flags](#time-date-related-flags) or -[Time, Date related settings](#time-date-related-settings) +## DateSlash +## DateDash +## DateDot +## DateSpace -## Date+Time entry / edit format +Access: -A real number with a `_date` unit attached is interpreted as a Date + Time -according to the format `YYYYMMDD.HHMMSS`. +Activate the corresponding date separator. -## Date+Time display format -By default a Date+Time is displayed on the stack like `Sun 30/Nov/2025, 16:43:10`. -The format can be adjusted by changing the [Time, Date related flags](#time-date-related-flags) or / and -[Time, Date related settings](#time-date-related-settings). +## DateSeparatorCommand -## Time format +Access: -The time format is `HH.MMSS` with optional hundredths of a second as -in `HH.MMSSCC`. +Return the most recent used or default date separator command. ## SetDate @@ -248,12 +318,18 @@ This displays on the stack as `HH:MM:SS`. ## JulianDayNumber -Return the Julian day number for the given date and time. +Access: [Date](#DateMenu) menu. + +Convert a date to its Julian day number. For dates the Gregorian calendar is assumed. The Gregorian calendar jumps from 1582-10-04 to 1582-10-15. -This command ignores that gap, so the Julian day number given by this command for dates on or before 1582-10-14 may deviate from other converters like -[The NASA Julian Date/Time Converter](https://ssd.jpl.nasa.gov/tools/jdc). +This command ignores that gap. +The Julian day number given by this command for dates on or before 1582-10-14 may deviate from other converters +like [The NASA Julian Date/Time Converter](https://ssd.jpl.nasa.gov/tools/jdc). + +The conversion uses software from the +[Standards of Fundamental Astronomy of the International Astronomical Union](https://www.iausofa.org/). To compute the Julian Day Number for the first day of the millenium: ```rpl @@ -261,18 +337,25 @@ To compute the Julian Day Number for the first day of the millenium: @ Expecting 2 451 544 ¹/₂ ``` -## Datefromjuliandaynumber +## DateFromJulianDayNumber + +Access: [Date](#DateMenu) menu. -Return the date for a given Julian day number. +Convert a Julian day number to its date. This command converts a Julian day number to a date in the Gregorian calendar. It is the opposite of the `JDN` command. +The conversion uses software from the +[Standards of Fundamental Astronomy of the International Astronomical Union](https://www.iausofa.org/). + ```rpl 2451545 JDN→ @ Expecting Sat 1/Jan/2000, 12:00:00 ``` +# Alarms and System Commands + ## ACK Acknowledge oldest alarm (dismiss) From 410086f8dd07107a296655cfe698d4288b85c45b Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Fri, 9 Jan 2026 14:02:07 +0100 Subject: [PATCH 14/16] src: Add JDN error handling. Before the errors of the SOFA funtions where ignored. Now there is basic error handling in the encapsulating functions. Signed-off-by: Ed@vanGasteren.net --- src/datetime.cc | 7 +++++-- src/tests.cc | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/datetime.cc b/src/datetime.cc index 718cfba5f..6813ccd67 100644 --- a/src/datetime.cc +++ b/src/datetime.cc @@ -245,7 +245,8 @@ double julian_day_number(int d, int m, int y) result = iauCal2jd(y, m, d, &djm0, &djm); if (result < 0) { - // ToDo: handle errors. + rt.invalid_date_error(); + return 0.0; } return (djm0 + djm); } @@ -278,7 +279,9 @@ algebraic_p date_from_julian_day(object_p jdn, bool error) result = iauJd2cal(dj1, dj2, &year, &month, &day, &jdn_fraction_of_day); if (result < 0) { - // ToDo: handle errors. + if (error) + rt.invalid_date_error(); + return nullptr; } bool negative_year = year < 0; diff --git a/src/tests.cc b/src/tests.cc index 2f6c0d777..74116d5fe 100644 --- a/src/tests.cc +++ b/src/tests.cc @@ -10118,8 +10118,10 @@ void tests::date_operations() .test(CLEAR, "19690217.03550197_date", ENTER) .expect("Mon 17/Feb/1969, 3:55:01.97"); step("Displaying invalid date and time") + .test(ID_HideDayOfWeek, ENTER) .test(CLEAR, "999999999.99999999_date", ENTER) - .expect("Tue 99/99/99999, 99:99:99.99"); + .expect("99/99/99999, 99:99:99.99") + .test(ID_ShowDayOfWeek, ENTER); step("Difference between two dates using DDays") .test(CLEAR, "20230908", ENTER) From 45be955b0edc5fc3ec32f7f768e3a21acb4e5d6c Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Fri, 9 Jan 2026 15:53:41 +0100 Subject: [PATCH 15/16] doc: improvements to Date and Time documentation Signed-off-by: Ed@vanGasteren.net --- doc/commands/system.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/commands/system.md b/doc/commands/system.md index cfbeb3ead..8c9172460 100755 --- a/doc/commands/system.md +++ b/doc/commands/system.md @@ -5,6 +5,7 @@ ## Date entry / edit format A whole number with a `_date` unit attached is interpreted as a date according to the customary format `YYYYMMDD`. + However, the year need not be a 4 digit number. It can a smaller, bigger, zero, even a negative number and leading zeros can be ommitted (as such it need not fit the `YYYY` format). @@ -40,12 +41,12 @@ The format can be adjusted by changing the [Date, Time flags](#date-time-flags) ## Time entry format -Enter the hours, a '.' to end the hours an begin the minutes. +Enter the hours, a '.' to end the hours and begin the minutes. After the minutes enter a second '.' to end the minutes and begin the seconds. The display will change to `°′_dms`, assuming you are entering an angle. Proceed with the seconds. Optionally you can give a third '.' followed by a fraction of a second. -Enter the fraction as numerator '.' (yes, a fourth; not a '/') denominator. +Enter the fraction as numerator '.' (yes, a fourth '.'; not a '/') denominator. Finally change the unit from `_dms` to `_hms`. With the cursor positioned before the unit you can just attach the `_hms` unit (it replaces the `_dms`). Or you can use the `→HMS` command. @@ -154,7 +155,7 @@ See: [Astronomical year numbering](https://en.wikipedia.org/wiki/Astronomical_ye ## DateDot ## DateSpace -Access: +Access: trough the `Date separator` entry in the `Status bar` menu. Activate the corresponding date separator. @@ -164,6 +165,7 @@ Activate the corresponding date separator. Access: Return the most recent used or default date separator command. +There is no DateSeparator variable to Recall. ## SetDate From b70071a86007cdba386730458bf175c6e696efc4 Mon Sep 17 00:00:00 2001 From: Ed van Gasteren Date: Sun, 15 Feb 2026 15:40:14 +0100 Subject: [PATCH 16/16] Improvements after review by @c3d. Signed-off-by: Ed@vanGasteren.net --- doc/6-ImplementationStatus.md | 6 +-- doc/commands/system.md | 74 +++++++++++++++++++++-------------- src/datetime.cc | 10 +++-- src/ids.tbl | 2 +- src/menu.cc | 8 ++-- 5 files changed, 59 insertions(+), 41 deletions(-) diff --git a/doc/6-ImplementationStatus.md b/doc/6-ImplementationStatus.md index 0c9444e88..50bf037d9 100644 --- a/doc/6-ImplementationStatus.md +++ b/doc/6-ImplementationStatus.md @@ -173,7 +173,7 @@ spellings. * `DateDash` * `DateDot` * `DateForeground` -* `DateMenu` +* `DatesMenu` * `DateSeparatorCommand` * `DateSlash` * `DateSpace` @@ -1124,7 +1124,7 @@ The following is an extensive list of commands. * `DateDash` * `DateDot` * `DateForeground` -* `DateMenu` +* `DatesMenu` * `DateSeparatorCommand` * `DateSlash` * `DateSpace` @@ -2073,7 +2073,7 @@ The following is an extensive list of commands. * `DateDash` * `DateDot` * `DateForeground` -* `DateMenu` +* `DatesMenu` * `DateSeparatorCommand` * `DateSlash` * `DateSpace` diff --git a/doc/commands/system.md b/doc/commands/system.md index 8c9172460..dada4f638 100755 --- a/doc/commands/system.md +++ b/doc/commands/system.md @@ -1,5 +1,5 @@ -# Date, Time +# Date and Time ## Date entry / edit format @@ -15,8 +15,8 @@ Months and days, even in a negative year, run from low (positive numbers) to hig Note: the date format is intentionally different from the format on the HP-48. Note: not all commands can handle a negative year. -The underlying platform DMCP of the SwissMicros calculators handles only positive years. -That bubbles up to several commands. +The DMCP platform for SwissMicros calculators only handles positive years. +This restriction bubbles up to several DB48x commands. ## Date display format @@ -28,7 +28,7 @@ The format can be adjusted by changing the [Date, Time flags](#date-time-flags) ## Date+Time entry / edit format -A real number with a `_date` unit attached is interpreted as a Date + Time +A decimal number with a `_date` unit attached is interpreted as a Date + Time according to the format `YYYYMMDD.HHMMSS`. @@ -41,18 +41,28 @@ The format can be adjusted by changing the [Date, Time flags](#date-time-flags) ## Time entry format -Enter the hours, a '.' to end the hours and begin the minutes. -After the minutes enter a second '.' to end the minutes and begin the seconds. -The display will change to `°′_dms`, assuming you are entering an angle. +This is based on the DB48x feature to quickly enter an angle value, +with repeated use of the _,_ (_._) key. +For example to enter, `2°03′05″`, +you can enter the sequence _2.3.5_. + +After the minutes, the second '.' will change the display to `°′_dms`, +assuming you are entering an angle. Proceed with the seconds. Optionally you can give a third '.' followed by a fraction of a second. Enter the fraction as numerator '.' (yes, a fourth '.'; not a '/') denominator. -Finally change the unit from `_dms` to `_hms`. -With the cursor positioned before the unit you can just attach the `_hms` unit (it replaces the `_dms`). -Or you can use the `→HMS` command. -That pushes the value on the stack. -Both the `_hms` unit and the `→HMS` command can be found in the [TimeMenu](#timemenu). -Or, in alpha mode, you can change the 'd' in an 'h'. + +Finally change the unit from `_dms` to `_hms`: +- With the cursor positioned between the last digit and the unit separator (`_`) +you can use the `_hms` menu button (it replaces the `_dms`). +- With the cursor positioned after the the unit separator (`_`) +you can use the _O_ (_x10n_, DM32/42/42n _E_) key (bound to the Cycle command) +to alternate between `_dms` and `_hms`. +- Or you can use the `→HMS` command. +But, that also pushes the value on the stack. +- Or, in alpha mode, you can change the 'd' in an 'h'. + +The `_hms` (InsertHms) and the `→HMS` (ToHMS) commands can be found in the [TimeMenu](#timemenu). A second way to enter a time is as `._hms`. @@ -73,9 +83,7 @@ If the fraction of a second is zero the '.' and the fraction will be left out. The `_hms` unit will not show. -## DateMenu - -Access: [Time](#TimeMenu) menu. +## DatesMenu Show a softkey menu for date-related commands, including: @@ -87,10 +95,10 @@ Show a softkey menu for date-related commands, including: * `JulianDayNumber` * `DateFromJulianDayNumber` +**Access:** [Time](#TimeMenu) menu. -## TimeMenu -Access: 🟦 _V_ (_TIME_) key. +## TimeMenu Show a softkey menu for time-related commands, including: @@ -106,6 +114,8 @@ Show a softkey menu for time-related commands, including: * `TimedEval` * `SetTime` +**Access:** 🟦 _V_ (_TIME_) key. + ## Date, Time flags @@ -120,16 +130,18 @@ Show a softkey menu for time-related commands, including: * `HideDayOfWeek` / `ShowDayOfWeek` * `BCECEyearNumbering` / `AstronomicalYearNumbering` +**Access:** + ## Date, Time settings * `DateSlash` / `DateDash` / `DateDot` / `DateSpace` * `DateSeparatorCommand` +**Access:** -## BCECEyearNumbering -Access: +## BCECEyearNumbering Activate the B(efore) C(ommon) E(ra) / C(ommon) E(ra) year numbering. @@ -138,10 +150,10 @@ This uses a non uniform timeline without a year = 0. The year numbering jumps from 1 BCE to 1 CE. So negative years are shifted. See: [Proleptic Gregorian calendar](https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar) +**Access:** -## AstronomicalYearNumbering -Access: +## AstronomicalYearNumbering Activate the Astronomical year numbering. @@ -149,24 +161,26 @@ Display negative years on the stack with a minus sign. This uses a uniform timeline including a year = 0. See: [Astronomical year numbering](https://en.wikipedia.org/wiki/Astronomical_year_numbering) +**Access:** + ## DateSlash ## DateDash ## DateDot ## DateSpace -Access: trough the `Date separator` entry in the `Status bar` menu. - Activate the corresponding date separator. +**Access:** trough the `Date separator` entry in the `Status bar` menu. -## DateSeparatorCommand -Access: +## DateSeparatorCommand Return the most recent used or default date separator command. There is no DateSeparator variable to Recall. +**Access:** + ## SetDate @@ -320,8 +334,6 @@ This displays on the stack as `HH:MM:SS`. ## JulianDayNumber -Access: [Date](#DateMenu) menu. - Convert a date to its Julian day number. For dates the Gregorian calendar is assumed. @@ -333,6 +345,8 @@ like [The NASA Julian Date/Time Converter](https://ssd.jpl.nasa.gov/tools/jdc). The conversion uses software from the [Standards of Fundamental Astronomy of the International Astronomical Union](https://www.iausofa.org/). +**Access:** [Date](#DatesMenu) menu. + To compute the Julian Day Number for the first day of the millenium: ```rpl 20000101 JDN @@ -341,8 +355,6 @@ To compute the Julian Day Number for the first day of the millenium: ## DateFromJulianDayNumber -Access: [Date](#DateMenu) menu. - Convert a Julian day number to its date. This command converts a Julian day number to a date in the Gregorian calendar. @@ -351,6 +363,8 @@ It is the opposite of the `JDN` command. The conversion uses software from the [Standards of Fundamental Astronomy of the International Astronomical Union](https://www.iausofa.org/). +**Access:** [Date](#DatesMenu) menu. + ```rpl 2451545 JDN→ @ Expecting Sat 1/Jan/2000, 12:00:00 diff --git a/src/datetime.cc b/src/datetime.cc index 6813ccd67..63a0b5a50 100644 --- a/src/datetime.cc +++ b/src/datetime.cc @@ -134,7 +134,8 @@ uint to_date(object_p dtobj, dt_t &dt, tm_t &tm, bool error) const uint days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; bool bisext = m == 2 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); - if (m < 1 || m > 12 || d < 1 || d > days[m-1] + bisext) + if (m < 1 || m > 12 || d < 1 || d > days[m-1] + bisext || + (Settings.BCECEyearNumbering() && y == 0)) { if (error) rt.invalid_date_error(); @@ -623,7 +624,7 @@ size_t render_date(renderer &r, algebraic_g date) date = date / factor; uint month = date->as_uint32(0, false) % 100; date = date / factor; - int year = date->as_uint32(0, false); + int year = date->as_int32(0, false); if (Settings.ShowDayOfWeek()) { @@ -640,6 +641,9 @@ size_t render_date(renderer &r, algebraic_g date) snprintf(mname, 4, "%u", month); bool zero_year = year == 0; + if (zero_year && !Settings.AstronomicalYearNumbering()) + return 0; + if ((negative_date || zero_year) && Settings.BCECEyearNumbering()) year = year + 1; if (negative_date && Settings.AstronomicalYearNumbering()) @@ -664,7 +668,7 @@ size_t render_date(renderer &r, algebraic_g date) { r.printf(" "); if (negative_date || zero_year) - r.printf("B"); + r.printf("B"); r.printf("CE"); } diff --git a/src/ids.tbl b/src/ids.tbl index e8ff0da71..f58d52d41 100644 --- a/src/ids.tbl +++ b/src/ids.tbl @@ -1343,7 +1343,7 @@ MENU(PrintingMenu) MENU(IOMenu) MENU(FilesMenu) MENU(TimeMenu) -MENU(DateMenu) +MENU(DatesMenu) MENU(AlarmMenu) MENU(PlotMenu) MENU(GraphicsMenu) diff --git a/src/menu.cc b/src/menu.cc index f0acdce3c..2b6e91435 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -198,7 +198,7 @@ static object::id unit_menu(unit_p u) result = object::ID_TimeMenu; else if (sym->matches("date") || sym->matches("d") || sym->matches("yr")) - result = object::ID_DateMenu; + result = object::ID_DatesMenu; } } return result; @@ -1773,11 +1773,11 @@ MENU(TimeMenu, "→Time", ID_SetTime, "→Date", ID_SetDate, "ClkAdj", ID_Unimplemented, - "Date", ID_DateMenu, + "Dates", ID_DatesMenu, "Alarms", ID_AlarmMenu); -MENU(DateMenu, +MENU(DatesMenu, // ---------------------------------------------------------------------------- // Date operations // ---------------------------------------------------------------------------- @@ -1809,7 +1809,7 @@ MENU(AlarmMenu, "AckAll", ID_Unimplemented, "Time", ID_TimeMenu, - "Date", ID_DateMenu); + "Dates", ID_DatesMenu); MENU(TextMenu,