Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MTC seconds roll to 60 #9

Open
mMerlin opened this issue May 31, 2024 · 6 comments
Open

MTC seconds roll to 60 #9

mMerlin opened this issue May 31, 2024 · 6 comments

Comments

@mMerlin
Copy link

mMerlin commented May 31, 2024

Are you still keeping an eye on this repo?

I spotted a bug in the MTC hh:mm:ss display. I am writing my own python based clock based on the glss algorithm information, and used Mars Clock as a cross check of my implementation.

The bug:
millis = 947,116,815,000 ¦ MTC 23:59:59
millis = 947,116,816,000 ¦ MTC 23:59:60
millis = 947,116,817,000 ¦ MTC 00:00:01

The seconds is rolling over from 59 to 60, instead of to zero and incrementing the minutes. That looks like the fractional seconds are being rounded for the seconds display value, but because it is not really the next second (minute) yet, the minutes do not increment. For a clock display, I think that should truncate (or use floor), so that the seconds value does not increment until the tenths of a second truly rolls over.

Those times are a few seconds off from what I expected from https://www.giss.nasa.gov/tools/mars24/help/algorithm.html and the near coincident worked example for 2000/01/06. 2000/01/06 00:00:00 should be MTC 23:59:39 (21 seconds before Mars midnight) A glance at the code shows that you are using a fixed value of 37 for the tai-utc offset. That likely accounts for the difference. I implemented a table lookup to handle the changing offset. Only works from 1972/01/01 forward.

@edgar-bonet
Copy link
Contributor

@mMerlin: You are right, the call to Math.round() in h_to_hms() should be Math.floor() instead.

It seems the original intent of the code was to round to the nearest second. If this is really what we want, then it can be achieved by rounding the total number of seconds rather than the ss field:

diff --git a/index.html b/index.html
index 9516c51..46e8c16 100644
--- a/index.html
+++ b/index.html
@@ -452,13 +452,13 @@
                 return Math.sin(deg * Math.PI / 180);
             }
             function h_to_hms(h) {
-                var x = h * 3600;
+                var x = Math.round(h * 3600);
                 var hh = Math.floor(x / 3600);
                 if (hh < 10) hh = "0" + hh;
                 var y = x % 3600;
                 var mm = Math.floor(y / 60);
                 if (mm < 10) mm = "0" + mm;
-                var ss = Math.round(y % 60);
+                var ss = y % 60;
                 if (ss < 10) ss = "0" + ss;
                 return hh + ":" + mm + ":" + ss;
             }

@mMerlin
Copy link
Author

mMerlin commented May 31, 2024

As noted in my initial issue report, my preference would be not use any rounding for a clock display. So

var x = Math.floor(h * 3600);

var ss = y % 60;

Just changing the the existing Math.round to Math.floor would do it as well.

Since I am working in Python, I have other options. Starting from an integer number of seconds, divmod does the job in 2 lines, then f-string formatting can be used to add any needed leading zeros. That function body becomes 4 lines (or 3 if the int() is embeded in the first divmod).

x = int(h * 3600) % 86400
y, ss = divmod(x, 60)
hh, mm = divmod(y, 60)
return f'{hh:02}:{mm:02}:{ss:02}'

Though I prefer more descriptive variable names.

@timparenti
Copy link

Agreed with @mMerlin. Modern H:M:S time displays pretty much universally truncate fractional seconds in the same way a simpler H:M display truncates the fractional minutes implied by hidden seconds.

As such, floor() definitely yields expected behavior, not round().

@jtauber
Copy link
Owner

jtauber commented Jul 2, 2024

Agreed on round -> floor. I'll fix this when I next get a chance (although a PR is welcome)

@jtauber
Copy link
Owner

jtauber commented Jul 2, 2024

@mMerlin Note that for some related Python work, you might want to look at my initial attempts a decade ago at https://github.com/jtauber/ephemerides

@mMerlin
Copy link
Author

mMerlin commented Jul 2, 2024

I browsed that. With the scenario I am working with, the details are a bit different, but the basic logic looks similar to prototype code I used along the way.

I did not exactly 'port' the mars-clock. I took the equations and constants from https://www.giss.nasa.gov/tools/mars24/help/algorithm.html, treated the listed constants as 'exact', then used basic algebraic operations to derive an equation that did not need any floating point operations. The target is a Mars Clock on an embedded device running CircuitPython. Limited hardware floating point precision. What I ended up with uses pure integer math to calculate right down to nanoseconds resolution. Which is the maximum resolution of the hardware timers. With other factors, accuracy is no where near that, but with an 'accurate' nanosecond linux timestamp, it gets a nanosecond accurate MTC. It's not even complex, once the algebraic operations merged all of the conversions that were happening in the algorithm page. I derived an 'exact' nanosecond (actually 1/1000 ns) offset from unix epoch to a specific MTC midnight. After that, it is simple nanoseconds per Mars day offsets, handled by divmod, leaving the nanoseconds since the previous Mars midnight. More divmod to convert to Mars hours, minutes, seconds, with a remainder in integer nanoseconds again.

Since I tend toward OCD, the link from that reference to PyEphem is interesting. I've always been 'annoyed' by the vagueness in most (news type) descriptions of positions in space.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants