You are browsing as a guest. Sign up (or log in) to start making projects!

libspacetime

  • 3 Devlogs
  • 3 Total hours

A C library for date and time functions on other planets. Initially, it was just going to be the proposed Darian calendar for Martian timekeeping, but I *think* the same person who made it, also proposed calendars for Jupiter. So in case that happens, this is "spacetime".

Open comments for this post

1h 44m 59s logged

libspacetime - mkmarstime function

Wow, what a sprint!

Part of the C date and time functions is mktime. It takes a struct tm object (which is a “broken down” time structure), and converts it into the time_t format (seconds since 1970). For libspacetime and the Darian Calendar, we need mkmarstime to track time on Mars.

In some ways, this ended up not being harder than I thought it was, and in some ways it did.

Leap Years

In the Gregorian Calendar, we have leap years every 4 years - except when the year is divisible by 100, unless divisible by 400. Yeah, it’s confusing.

The Darian Calendar, in it’s wording from the website and also Wikipedia confused me. I thought Intercalation was the length of a year, but no, it’s actually just getting the # of leap years that have passed at a given year number.

Darian Calendar rules are actually, every odd numbered year is a yeap lear, except for decades (10, 20, 30). Exception to that is if the year is divisible by 100, and again for divisible by 1000.

In the commented code, you can see how I put down my train of thought, but ended up coming to what the actual source was anyway.

Basically, you find the number of leap years, multiply by 669 days, then non-leap years, multiply by 668.

Fun fact: Glibc in its tm structures, according to POSIX specs, starts the year at 0. I believe it is because it could make those numbers fit in a smaller data structure. For us, the Darian year is 221. I guess I could maybe try to shave it down? But these are things I’ll have to decide before any release.

Months

Every month has 28 days, except for the last month in each “quarter”, which has 27.

You could calculate this, but Glibc, for the Gregorian Calendar actually has a static table that lists the amount of days since each month starts. This way it doesn’t have to do the multiplication every time.

I was doing it manually, and I was going to write out the expressions - 281, 282, etc. but it got complicated when also having to add like, 287 + (271) and I didn’t know which I was on track for. By using the example website, I got the numbers by manual conversion.

Leap Days

The table makes sense in Glibc for another reason: The leap day in the Gregorian Calendar is so early in the year, it shifts every day forward by one.

In the Darian Calendar, the leap day is actually at the end of the last month of the year. So we don’t need to store duplicate entries, or actually really worry about it for this function. (Not sure whether it is my job to handle invalid values). But basically if the current year is a leap year, we can still work as normal, and then just add on the day as requested. Nice!

The rest

Days, hours, minutes, seconds are all as normal.

The epoch

The Darian Calendar epoch actually begins in 1609. But.. the Mars Sol Date, which is unofficial but even used in NASA’s Mars24 program, has its “0” date at Dec 29 1873. So we need to subtract to make up for the difference.

If you use dates before MSD 0, you get negative mars_time_t values.

I couldn’t figure out what the epoch meant, until I realized it was just MSD 0. I also found that marsclock.com’s “midday” is actually off by about 177 seconds. But I calculated MSD 0 to be what you see in the code (I need to save characters so I can submit this), and off I went.

Testcases

Yeah, this needs tests. Even more than what I put in for this devlog (MSD 0 and Unix Epoch 0).

Unfortunately in Mars -> Earth time, I am losing about an Earth second in conversion. I’ll try to debug this now. But it causes some tests, like the epoch to be incorrect - it returns a mars_time_t of what would be unix epoch -1.

Overall thoughts

The genius of how Glibc handles the months was probably the coolest part. Most challenging, the leap year intercalation for sure.

Now, onto more test suites, and more functions.

libspacetime - mkmarstime function

Wow, what a sprint!

Part of the C date and time functions is mktime. It takes a struct tm object (which is a “broken down” time structure), and converts it into the time_t format (seconds since 1970). For libspacetime and the Darian Calendar, we need mkmarstime to track time on Mars.

In some ways, this ended up not being harder than I thought it was, and in some ways it did.

Leap Years

In the Gregorian Calendar, we have leap years every 4 years - except when the year is divisible by 100, unless divisible by 400. Yeah, it’s confusing.

The Darian Calendar, in it’s wording from the website and also Wikipedia confused me. I thought Intercalation was the length of a year, but no, it’s actually just getting the # of leap years that have passed at a given year number.

Darian Calendar rules are actually, every odd numbered year is a yeap lear, except for decades (10, 20, 30). Exception to that is if the year is divisible by 100, and again for divisible by 1000.

In the commented code, you can see how I put down my train of thought, but ended up coming to what the actual source was anyway.

Basically, you find the number of leap years, multiply by 669 days, then non-leap years, multiply by 668.

Fun fact: Glibc in its tm structures, according to POSIX specs, starts the year at 0. I believe it is because it could make those numbers fit in a smaller data structure. For us, the Darian year is 221. I guess I could maybe try to shave it down? But these are things I’ll have to decide before any release.

Months

Every month has 28 days, except for the last month in each “quarter”, which has 27.

You could calculate this, but Glibc, for the Gregorian Calendar actually has a static table that lists the amount of days since each month starts. This way it doesn’t have to do the multiplication every time.

I was doing it manually, and I was going to write out the expressions - 281, 282, etc. but it got complicated when also having to add like, 287 + (271) and I didn’t know which I was on track for. By using the example website, I got the numbers by manual conversion.

Leap Days

The table makes sense in Glibc for another reason: The leap day in the Gregorian Calendar is so early in the year, it shifts every day forward by one.

In the Darian Calendar, the leap day is actually at the end of the last month of the year. So we don’t need to store duplicate entries, or actually really worry about it for this function. (Not sure whether it is my job to handle invalid values). But basically if the current year is a leap year, we can still work as normal, and then just add on the day as requested. Nice!

The rest

Days, hours, minutes, seconds are all as normal.

The epoch

The Darian Calendar epoch actually begins in 1609. But.. the Mars Sol Date, which is unofficial but even used in NASA’s Mars24 program, has its “0” date at Dec 29 1873. So we need to subtract to make up for the difference.

If you use dates before MSD 0, you get negative mars_time_t values.

I couldn’t figure out what the epoch meant, until I realized it was just MSD 0. I also found that marsclock.com’s “midday” is actually off by about 177 seconds. But I calculated MSD 0 to be what you see in the code (I need to save characters so I can submit this), and off I went.

Testcases

Yeah, this needs tests. Even more than what I put in for this devlog (MSD 0 and Unix Epoch 0).

Unfortunately in Mars -> Earth time, I am losing about an Earth second in conversion. I’ll try to debug this now. But it causes some tests, like the epoch to be incorrect - it returns a mars_time_t of what would be unix epoch -1.

Overall thoughts

The genius of how Glibc handles the months was probably the coolest part. Most challenging, the leap year intercalation for sure.

Now, onto more test suites, and more functions.

Replying to @jpeisach

0
1
Open comments for this post

23m 8s logged

Earth Timekeeping to Mars Timekeeping Conversions

Because I’m going out to see family today - might as well get something done. I was going to add “mktime” but I realized that I’ve done Mars to Earth but not vice versa. Besides, I need an “epoch” to start time from.

Technically, I already had done this with mars_time(), I just needed to do it with any timestamp. I did “0” (January 1, 1970, midnight) locally to verify, then chose the Mariner 9 enter orbit as a testcase.

I will note, Wikipedia shows MSD (Mars Sol Date) but also Mars Julian Sol. I wonder if I’ll have to do that later.

I also will probably need to organize my tests/Makefile.am for further testcases. It will grow once I start adding time tests and not just MSD.

Earth Timekeeping to Mars Timekeeping Conversions

Because I’m going out to see family today - might as well get something done. I was going to add “mktime” but I realized that I’ve done Mars to Earth but not vice versa. Besides, I need an “epoch” to start time from.

Technically, I already had done this with mars_time(), I just needed to do it with any timestamp. I did “0” (January 1, 1970, midnight) locally to verify, then chose the Mariner 9 enter orbit as a testcase.

I will note, Wikipedia shows MSD (Mars Sol Date) but also Mars Julian Sol. I wonder if I’ll have to do that later.

I also will probably need to organize my tests/Makefile.am for further testcases. It will grow once I start adding time tests and not just MSD.

Replying to @jpeisach

0
3
Open comments for this post

1h 17m 19s logged

libspacetime - creating a testsuite

But first, pre-stardance talk

I’ve known the Darian Calendar existed, and my goal is to spend my time over the summer to try to make it as close to system level support as possible. This includes trying to get it at kernel-level - which is another project.

Anyways, libspacetime is basically time.h but for other planets. I want it to be portable and work on as many systems as possible. For this reason I setup a GNU Autotools project (autoconf, automake, that fun stuff).

Now, the Darian calendar is not standard, but C date and time functions are. Also, timekeeping is actually complicated. So I’m kind of.. mimicking the standards, and I may not get there in terms of implementation for a while, but I try my best.

Using some sites:

And after fighting with type versions, I eventually got a current unix time, represented in Martian seconds, in a way that you can get to the current Mars Sol Date (MSD).

Uh.. I’m not a mathematician. How does the timekeeping and conversions work, I honestly don’t know off hand. This will prove to continue being a challenge… especially because like, “ok, so what is our “epoch” for mars? Still Jan 1 1970 on Earth? But the existing proposed calendar conversions use this date instead?” - lots of fun in the future.

Okay, basically pre stardance was just mars_time and the initial project.

Creating the testsuite

For test runners, there are options - TAP, DejaGNU, etc. But this isn’t Meson where you can setup test targets.

Autotest is kind of weird (that seems to be the general consensus). If you are testing executable programs, it’s great, because you can get a fixed output. But at the base level, it’s really just a bunch of shell scripts.

So in test “setup”, I want to compile my “tests”. But a user building the library may not have libspacetime headers or library installed, so we need to not only build a C target (which in itself is weird, the GNU Autotools docs for test suites doesn’t suggest this as far as I know), but we need to link against the library built in the src folder of the project and also include its headers. Kinda janky.

The lack of useful documentation examples is what I spent a lot of time on. There is also the thing with atlocal, which I think is like.. empty? But docs suggest it should be generated?

package.m4 files exist now, which I did a great job filling out now that I look back at it -_-

when it comes to actual test checks (testsuite.at), apparently it compares output, not status code.. so I have to like, verbatim tell “I expect this output”. So there goes printing out the status of the current times I am testing.

Also it is so specific, like I can’t use a newline character in the printf in the test executable.

The print is useful because a round conversion from Earth -> Martian -> Earth results in a one earth second loss. I don’t know if it’s because of floating point precision or because of the time it takes to execute the conversion from the processor.

Ideally, the application can ask the kernel for the time and it uses its own clocks - which can use a counter chip, and using the amount of increases per a set of time, can figure out how long a “cycle” is and keep time that way. That was sort of the goal of my kernel “spacetime” support, but I wanted it to show up in lsclocks, and after all clocksource is like, a hardware abstraction, not an actual clock. Idealy a clocksource could just have a lower multiplier, but the kernel still uses the best clocksource which certainly won’t be the martian one.

Anyways, use janky tools (Autotest framework), get janky results. Cheers to more date and time functions and tests.

libspacetime - creating a testsuite

But first, pre-stardance talk

I’ve known the Darian Calendar existed, and my goal is to spend my time over the summer to try to make it as close to system level support as possible. This includes trying to get it at kernel-level - which is another project.

Anyways, libspacetime is basically time.h but for other planets. I want it to be portable and work on as many systems as possible. For this reason I setup a GNU Autotools project (autoconf, automake, that fun stuff).

Now, the Darian calendar is not standard, but C date and time functions are. Also, timekeeping is actually complicated. So I’m kind of.. mimicking the standards, and I may not get there in terms of implementation for a while, but I try my best.

Using some sites:

And after fighting with type versions, I eventually got a current unix time, represented in Martian seconds, in a way that you can get to the current Mars Sol Date (MSD).

Uh.. I’m not a mathematician. How does the timekeeping and conversions work, I honestly don’t know off hand. This will prove to continue being a challenge… especially because like, “ok, so what is our “epoch” for mars? Still Jan 1 1970 on Earth? But the existing proposed calendar conversions use this date instead?” - lots of fun in the future.

Okay, basically pre stardance was just mars_time and the initial project.

Creating the testsuite

For test runners, there are options - TAP, DejaGNU, etc. But this isn’t Meson where you can setup test targets.

Autotest is kind of weird (that seems to be the general consensus). If you are testing executable programs, it’s great, because you can get a fixed output. But at the base level, it’s really just a bunch of shell scripts.

So in test “setup”, I want to compile my “tests”. But a user building the library may not have libspacetime headers or library installed, so we need to not only build a C target (which in itself is weird, the GNU Autotools docs for test suites doesn’t suggest this as far as I know), but we need to link against the library built in the src folder of the project and also include its headers. Kinda janky.

The lack of useful documentation examples is what I spent a lot of time on. There is also the thing with atlocal, which I think is like.. empty? But docs suggest it should be generated?

package.m4 files exist now, which I did a great job filling out now that I look back at it -_-

when it comes to actual test checks (testsuite.at), apparently it compares output, not status code.. so I have to like, verbatim tell “I expect this output”. So there goes printing out the status of the current times I am testing.

Also it is so specific, like I can’t use a newline character in the printf in the test executable.

The print is useful because a round conversion from Earth -> Martian -> Earth results in a one earth second loss. I don’t know if it’s because of floating point precision or because of the time it takes to execute the conversion from the processor.

Ideally, the application can ask the kernel for the time and it uses its own clocks - which can use a counter chip, and using the amount of increases per a set of time, can figure out how long a “cycle” is and keep time that way. That was sort of the goal of my kernel “spacetime” support, but I wanted it to show up in lsclocks, and after all clocksource is like, a hardware abstraction, not an actual clock. Idealy a clocksource could just have a lower multiplier, but the kernel still uses the best clocksource which certainly won’t be the martian one.

Anyways, use janky tools (Autotest framework), get janky results. Cheers to more date and time functions and tests.

Replying to @jpeisach

0
1

Followers

Loading…