msgpack-timestamp 0.1.0

Parse/serialise MessagePack extension -1 timestamps (no_std, no integration)
Documentation
#include <ctime>
#include <err.h>
#include <errno.h>
#include <fstream>
#include <map>
#include <msgpack.hpp>
#include <sys/stat.h>
#include <utility>

// Positive max:
//   > DateTime.from_unix((253402214400+24*60*60-1)*1000000000+999999999, :nanosecond)
//   {:ok, ~U[9999-12-31 23:59:59.999999Z]}
//   > DateTime.from_unix((253402214400+24*60*60-1)*1000000000+999999999+1, :nanosecond)
//   {:error, :invalid_unix_time}
//
// Negative max:
//   > DateTime.from_unix(-377705116800*1000000000, :nanosecond)
//   {:ok, ~U[-9999-01-01 00:00:00.000000Z]}
//   > DateTime.from_unix(-377705116800*1000000000-1, :nanosecond)
//   {:error, :invalid_unix_time}
//
// This affects
//   timestamp96nid
//   timestamp96nax
//   timestamp96mid
//   timestamp96max

// unsigned 32-bit tv_sec, tv_nsec = 0
static const struct timespec timestamp32min = {.tv_sec = 0};                   // 1970-01-01T00:00:00+00:00
static const struct timespec timestamp32mid = {.tv_sec = 1765301648};          // 2025-12-09T17:34:08+00:00
static const struct timespec timestamp32max = {.tv_sec = 0x00000000FFFFFFFF};  // 2106-02-07T06:28:15+00:00

// unsigned 34-bit tv_sec, tv_nsec != 0
static const struct timespec timestamp64min = {.tv_sec = 0, .tv_nsec = 1};                             // 1970-01-01T00:00:00+00:00
static const struct timespec timestamp64mid = {.tv_sec = 1765301648, .tv_nsec = 500000000};            // 2025-12-09T17:34:08+00:00
static const struct timespec timestamp64max = {.tv_sec = 0x00000003FFFFFFFF, .tv_nsec = 999'999'999};  // 2514-05-30T01:53:03+00:00

// signed 64-bit tv_sec
static const struct timespec timestamp96nin = {.tv_sec = -1, .tv_nsec = 999'999'999};           // 1969-12-31T23:59:59+00:00
static const struct timespec timestamp962in = {.tv_sec = -2, .tv_nsec = 999'999'999};           // 1969-12-31T23:59:58+00:00
static const struct timespec timestamp96nid = {.tv_sec = -188852558399, .tv_nsec = 500000000};  // -4015-07-02T12:00:01+00:00
static const struct timespec timestamp96nax = {.tv_sec = -377705116800, .tv_nsec = 0};          // -9999-01-01T00:00:00+00:00

static const struct timespec timestamp96min = {.tv_sec = 0x00000003FFFFFFFF + 1, .tv_nsec = 0};                     // 2514-05-30T01:53:04+00:00
static const struct timespec timestamp96mid = {.tv_sec = 135291084991, .tv_nsec = 500000000};                       // 6257-03-16T00:56:31+00:00
static const struct timespec timestamp96max = {.tv_sec = 253402214400 + 24 * 60 * 60 - 1, .tv_nsec = 999'999'999};  // 9999-12-31T23:59:59+00:00

static const std::pair<const char *, struct timespec> timespecs[] = {
    {"timestamp32min", timestamp32min}, {"timestamp32mid", timestamp32mid}, {"timestamp32max", timestamp32max},  //
    {"timestamp64min", timestamp64min}, {"timestamp64mid", timestamp64mid}, {"timestamp64max", timestamp64max},  //
    {"timestamp96nin", timestamp96nin}, {"timestamp962in", timestamp962in}, {"timestamp96nid", timestamp96nid}, {"timestamp96nax", timestamp96nax},
    {"timestamp96min", timestamp96min}, {"timestamp96mid", timestamp96mid}, {"timestamp96max", timestamp96max}};


int main(int, const char * const * argv) {
	auto destdir = argv[1] ?: ".";
	if((mkdir(destdir, 0777) == -1 && errno != EEXIST) || chdir(destdir))
		err(1, "%s", destdir);

	for(auto [name, ts] : timespecs)
		for(auto trunc : {""}) {
			{
				std::ofstream outf{std::string{name} + trunc + ".msgpack"};
				msgpack::pack(outf, ts);
			}
		}
}