Does anyone need Glk date structs to be normalised?

Glk has a rarely used feature to normalise date structs. Basically if you give glk_date_to_simple_time_utc a date struct with 2025/10/-3 17:107 fields then it will normalise each field before calculating the final time (going back to Sept 28, or forward into the 18th hour).

I suspect this was basically a freebee with the C function timegm. But in other languages it’s not so easy. Now that I’m using Rust I think the code to handle normalising dates is taking up to about 5% of the final filesize of the WASM build of Glulxe.

The Glk spec says that “If the time cannot be represented by the platform’s time library, this may return -1”, and I’m considering doing that instead. Unless someone really needs normalised dates?

1 Like

What are normalised dates?

-Wade

Normalised dates are proper dates! No negative days of the month, no minutes over 59, etc. “Normalisation” is the process of taking bizarro world dates and processing them, turning Oct -3 into Sept 28 etc. RemGlk-rs does this currently, but I’m thinking of just returning an error instead.

I think this one is tricky, as you could end up relying on the normalization logic without really thinking about it, especially if you’re not an experienced programmer. if your code is tracking, for example, some date and time, and you want to advance that time by (say) two hours, it’s easy to add two to the hours variable and use that. But without normalization, that will usually work, but not if the time happened to be after 10pm. With normalization, that always works.

3 Likes

Yeah, that’s what I was thinking when I wrote this up, I’m afraid. It didn’t occur to me that a language would ditch libc.

I’m not sure anybody’s using these functions at all, outside of test cases. But I haven’t done a survey.

Strikes me as a good candidate for the development cutting-room floor.

Yes, well, it’s not in development. It’s been documented and implemented since 2011.

At least the spec gives me an out, if I decide I want to take it. Sort of.. I did have to implement the normalising of dates myself which I think counts as not being supported by the library.

Well the question is whether anyone would be doing that rather than adding to a timestamp. I’d guess that almost all uses of the Glk date struct are just for printing dates, not doing calculations with.

Times like this it would really be good if we could somehow survey the Glulx games in the archive to see what Glk calls they make!

I fear I had misread Danni’s quote from the spec as indicating that it was acceptable to return -1 if the platform’s time library didn’t support date normalization, and so I thought Danni cutting the code from RemGlk-rs and just returning -1 seemed like it was within bounds.

I see now what it really says.

Is that not what it says? Neither Chrono not Jiff had anything like timegm. I’ve been able to implement it myself, but at a cost of about 4% of the wasm binary size. Or do you think it more was referring to if a library didn’t support 64bit timestamps or something?

Also, I could make it an option, so it was only excluded when building to wasm. With the possibility to include it again if someone really needed it.

glsi32 glk_date_to_simple_time_utc(glkdate_t *date, glui32 factor);
glsi32 glk_date_to_simple_time_local(glkdate_t *date, glui32 factor);

Convert the broken-out structure (interpreted as universal or local time) to a timestamp
divided by factor. The weekday value in glkdate_t is ignored. The other values need not be in their normal ranges; they will be normalized.

If the time cannot be represented by the platform’s time library, this may return −1.

It’s not granting permission for an implementation to return -1 if the platform library doesn’t support date normalization; it’s saying that if the result of processing the arguments isn’t a valid time (as reckoned by the local platform’s time library), these functions might return -1 (as one might expect if they were implemented by wrapping timegm).

So it’s not suggesting that attempting date normalization is optional; it’s just describing what happens if even date normalization can’t turn the arguments into something reasonable. (Or at least that’s how I’m reading it now…)

There is another option: just use the libc timegm function’s Rust binding. It would probably decrease the wasm size quite a bit, though Emscripten does move some of its implementation into JS.

But do I want to do that? No. I wrote RemGlk-rs to use a safe modern language. I don’t want to have lots of calls to unsafe functions (eventually I’d like to ban unsafe code in the core remglk, and for the only unsafe code in remglk_capi to be the unavoidable FFI calls.) I’m using Serde even though it increases the file size a lot compared to hand parsing the JSON because I want RemGlk-rs to be the kind of library that doesn’t have to hand parse JSON.

So if the consensus is that I should keep date normalising, then I’ll do so just using Jiff, even if it is bigger. (Though I think I could still reduce it somewhat by avoiding the panicing functions…)

1 Like