cosinekitty / astronomy

Astronomy Engine: multi-language calculation of Sun, Moon, and planet positions. Predicts lunar phases, eclipses, transits, oppositions, conjunctions, equinoxes, solstices, rise/set times, and other events. Provides vector and angular coordinate transforms among equatorial, ecliptic, horizontal, and galactic orientations.
MIT License
496 stars 64 forks source link

Minor enhancement: Keep the date part in solar_time.c (and equivalent files) #333

Closed piula closed 7 months ago

piula commented 9 months ago

Hello,

first of all I must say that I've rarely seen such a high-quality, well-structured, well-thought and well-documented piece of code. I've ported the parts I need to Object Pascal and I had to struggle with this job.

My request is about the calculation of true solar time. There's an example for every language, but unfortunately they all truncate the date part. I've tried myself but I don't know how to get it right. So my enhancement request is a function to get true solar time as type astro_time_t.

Thank you.

cosinekitty commented 9 months ago

Hi @piula and thank you for the suggestion. I wanted to reply before too many more days went by. I am very focused on another project right now, and I hope some time will free up next week for me to look at this. It does make sense to me on the surface. Once I get some free time to study it, I will reply again back on this issue.

piula commented 9 months ago

Thank you very much, this would be great. Take your time, no need to hurry.

Reading my initial post again, I have to apologize for a very bad typo there: what I meant is that "I never had to struggle with" porting your code to pascal. It was very straightforward! Sorry for the mistake.

cosinekitty commented 8 months ago

Hi again @piula, and sorry for the delay in responding. Can you tell me more why you want the result as astro_time_t? The reason I ask is, the question is confusing me. When you call Astronomy_HourAngle, you already know the exact UTC date and time. The solar time is a local angular phenomenon, not a UTC date and time. It's not even a time that anyone typically uses on a clock.

Part of the problem with the date is I would have to know the international date line in order to guess the date correctly. This is a political question, not a scientific question, and is always subject to change by governments and treaties.

I have resisted requests to handle local time zones, daylight savings time, etc, and this is a similar problem. Generally your browser and/or operating system already provides support for understanding time zones and dates, and you should be able to convert the UTC value in time to your local date and time. Then you can use the date part, in combination with the hour angle, to format as a sort of quasi-date/time.

I hope this helps!

piula commented 8 months ago

Thank you for your feedback.

If my understanding is correct, the actual hour angle (as printed by the hour angle example) is connected to the mean hour angle (as given by the time zone) by the equation of time (EOT). EOT has a span from approx. -18 minutes to +18 minutes. The mean hour angle has a date part, so adding or subtracting a few minutes should keep the date part, imho.

For the background: I replaced an existing astronomy component (which originated from a crude python script) with your well-thought and much better maintainable astronomy engine. I have already replaced everything, but a small value is missing: the apparent solar time for a given UTC time. If I'm not completely wrong, the time part is identical to the hour angle. But I couldn't manage to get the date part, yet.

Based on your example, I thought that I need something like this:

// Calculate Greenwich Apparent Sidereal Time (GAST) at the given time.
gast := SiderealTime (FTime);

// Obtain equatorial coordinates of date for the body.
ofdate := Equator (BODY_SUN, FTime, FObserver, EQUATOR_OF_DATE, ABERRATION);
IF NOT (ofdate.status = ASTRO_SUCCESS) THEN Exit (NaN);

// start with provided date and time
Result := ReturnDate (FTime, tzLocal);

v := FMod (FObserver.Longitude / 15.0 + gast - ofdate.ra, 24.0) + 12.0;
IF (v < 0.0) THEN BEGIN
  Result := IncDay (Result, -1);
  v += 24.0;
END ELSE IF (v > 24.0) THEN BEGIN
  Result := IncDay (Result);
  v -= 24.0;
  END;

x := Trunc (v * 3600000); // ms
ms := x MOD 1000;
x := x DIV 1000;
s := x MOD 60;
x := x DIV 60;
m := x MOD 60;
h := x DIV 60;
Result := RecodeTime (Result, h, m, s, ms);

But I think that it is wrong, even though I have forgotten my exact test case in the meantime :)) (no offense!)

I think the problem was near +/-180° meridian. I have rough time zone management included in my app, so I'd help me to know how to get apparent solar time (with date) either in local timezone or in UTC. I'd equally help me to get EOT with correct sign.

Thank you for your patience.

cosinekitty commented 8 months ago

Your operating system API should have some mechanism for converting time zones. I don't know whether access to time zone calculation is available in your Pascal compiler. But the idea is, you should be able to convert from the UTC value you started with (completely side-stepping all astronomy issues), and convert it to your local time zone, including the date. Then you can keep the date part and combine it with the solar hour angle as you do above. I believe this will always work so long as you are not close to midnight in solar time. There you may have to include special logic to detect this case and add/subtract a day from your date as needed.

piula commented 7 months ago

Ok, thank you.