POV-Ray : Newsgroups : povray.programming : Time for a Rant Server Time
7 Dec 2021 09:37:49 EST (-0500)
  Time for a Rant (Message 1 to 9 of 9)  
From: clipka
Subject: Time for a Rant
Date: 16 Aug 2021 18:45:56
Message: <611aeaa4$1@news.povray.org>
I haven't done a good old rant lately, have I?

Well, this is the time, and this is the day.

Speaking of which, did you know just what a clusterf*** time and date 
related programming in C/C++ is? Or, as a matter of fact, in general?


Okay, boost's date_time library worked. Boost seems to have a tendency 
to do that, I do give them that.

Yes, it did work... for UTC. That's GMT for the old timers. Except it's 
not. Or it may be. Depends on who's talking. Could be plain UT instead 
for all we know. Also, historically, for some time GMT-based dates 
started at noon. So nobody in their sane mind should really use GMT to 
denote universal points in time. Not that there is such thing as a 
universal point in time anyway (Thanks, Einstein)... but I think I might 
be digressing a little... so, boost worked nicely for UTC.

But if, instead of UTC, you want to play with times and dates in local 
time, you need to use time zones.

Now there _is_ a timezone sub-library in boost date_time, and it is 
designed to integrate neatly with the rest of date_time, so no big deal, 
right?


Except, said timezone library provides NO way to get the timezone 
matching the system's locale. Because that, I guess, would be too common 
a use case, and would make life too easy for programmers. You know how 
you have to present challenges to zoo animals every once in a while so 
they don't get mentally ill? I think it's the same for programmers. 
Seems like boost got that message.

Granted, there's an interface to get timezone XY. But good luck 
detecting that the system's locale uses timezone XY in the first place. 
Sure, every operating system worth its price (or even just a fraction 
thereof) provides a function to get the name of the current timezone. 
But of course some OSes don't bother to follow any of the established 
standards (of which there are multiple of course) for timezone names, 
except their own. (Where have I seen this before? And what OS could I 
possibly be looking at?) And of course that's precisely the one boost 
refuses to recognize (which also deserves a reproachful stare).

Now you _could_ possibly use some other functions to try and detect the 
offset from UTC, and then construct an ad-hoc time zone from that. But 
that won't work reliably for dates other than today, because this won't 
tell you whether Daylight Savings Time is in effect today, nor whether 
that may be different from the day in question.


Speaking of DST - did you know that there are entire databases of what 
Daylight Savings Time rules were in effect in what country in what time 
period? And your operating system probably has one of those. Which may 
or may not be up-to-date, but it's the best we can get.


So why not ditch boost date_time altogether, and use good old standard C 
library functions. If _those_ don't know the proper time zone, and 
whether DST applied, or will apply (presumably, based on current rules), 
for any given date you name, nobody does.

There are a couple of standard functions defined to convert between a 
semi-universal "point in time" data type (`time_t`) and a data type 
holding Gregorian date and time data (`tm`).


Except, those functions are not thread-safe. Which is kind of a 
deal-breaker in a multithreaded application. And besides, our automated 
source code analysis tool would bicker about it, for exactly that reason.


Well, fortunately there are thread-safe alternatives provided by the 
operating systems.

Phew.

Not that there is any universal standard for them. Because, again, that 
would be too easy.

So where e.g. POSIX systems have `localtime_r()` to replace 
`localtime()`. Windows has `_localtime_s()`.

Not to be confused with `localtime_s()`, which is a standard function in 
C (C11 and later to be precise). Which still hasn't been adopted into 
any C++ standard. And has a different parameter order than Windows' 
`_localtime_s()` - because zoo animals I guess.

But those functions do exist, for each of the original thread-unsafe C 
functions.


So there's functions to convert to and from Gregorian date and time, in 
both local time and UTC variants.


Except for the conversion _from_ Gregorian time. There's only one 
variant for those. Guess which one.

If you guessed that variant was the UTC one - because it's easier to 
implement, since the point-in-time data type is also universal rather 
than local time - then you may guess again.


Yeah. No way to convert a Gregorian date and UTC time to that 
point-in-time type, which is also UTC based.

Well, there is such a function on sone Unixoid systems, and oddly enough 
for onece GNU and BSD agree there. But not on Windows. And not even on 
generic POSIX.

*Sigh*.

Now you _could_ roll your own function to do this computation. Dig up a 
formula to convert any Gregorian date to a linear day (say, Modified 
Julian Date), subtract an offset so that you get a zero for 1970-01-01, 
multiply by 24*60*60, add the time, and shove that value into `time_t`. 
Because that's how that type works, right? POSIX time. Seconds since 
1970-01-01, 00:00 UTC.

Well, not so fast. Because nowhere does the C or C++ standard mandate 
that `time_t` actually work that way.

And as a matter of fact on most systems it doesn't. Though that's 
actually all the better for the computations.

Because leap seconds. Did you ever spare a thought for them?
Not all days are created equal. Some are 24*60*60+1 seconds long. And 
some could be, theoretically, as short as 24*60*60-1 seconds.
The former tends to happen about every one or two years, and the 
astronomy boffins decide when it's time to insert another one.

To compute how many seconds have actually elapsed since any given date 
and time, we'd have to consult a database of leap seconds.

Without that, our homebrew formula would only work if days were always 
24*60*60 seconds long. And fortunately that's exactly how POSIX time 
_actually_ works: Its base unit isn't seconds at all. It's calendar 
days, except that they're scaled by a factor of 24*60*60, and with time 
of day in seconds added.


Except on systems where it isn't. Which use POSIX-ish time _including_ 
leap seconds. And while they're rare, they still exist. Or, at least 
hypothetically, systems where `time_t` runs faster than seconds. Or 
slower; even that could be conceivable without violating the C standard. 
So if we need to resort to such homebrew math, we should at least 
implement a check on start-up to verify that the point-in-time data type 
is in fact genuine POSIX time.


Fortunately we only need a homebrew function for one of those Gregorian 
Date conversions...


... as log as we don't care about dates before 1970.


Because, as it turns out, on Windows those functions report an error for 
any point in time earlier than 1970-01-01 00:00 UTC. Or at least that's 
what the documentation claims. In reality, you can't even rely on that: 
A couple of hours before are fine, too. But no more than that.

On Unix at least there only seems to be some wonkiness for a very 
specific 1-second interval around that time, namely 1969-12-31 23:59:59 
UTC. Because apparently someone thought that value would make for a nice 
choice to signal an error. (Did I mention my zoo animal hypothesis?)


So, yay. Hooray for date and time manipulation in C/C++.

I can't wait till the day we require C++20 to build POV-Ray. That's the 
time and day when things will get...
... better? Well, different, anyway.


Post a reply to this message

From: jr
Subject: Re: Time for a Rant
Date: 16 Aug 2021 19:35:00
Message: <web.611af5874e7f92855e0fed26cde94f1@news.povray.org>
hi,

clipka <ano### [at] anonymousorg> wrote:
> I haven't done a good old rant lately, have I?
> Well, this is the time, and this is the day.

commiserations.  (though I did enjoy the read, some of it was tinged with
sympathy. :-))

> ...
> Granted, there's an interface to get timezone XY. ...

would 'tzset(3)' help?  (POSIX + thread-safe, but *NIX only, I guess)


regards, jr.


Post a reply to this message

From: clipka
Subject: Re: Time for a Rant
Date: 17 Aug 2021 04:48:14
Message: <611b77ce@news.povray.org>
Am 17.08.2021 um 01:32 schrieb jr:

>> Granted, there's an interface to get timezone XY. ...
> 
> would 'tzset(3)' help?  (POSIX + thread-safe, but *NIX only, I guess)

No; that would be the way to determine the timezone name on Unix, with 
which you could then get a boost timezone. But, as you already noticed, 
it doesn't exist on Windows.


Also, boost date_time timezones aren't really an ideal solution anyway. 
They presume that the local time rules are immutable for any given 
locale, when in reality they can vary.

When the `TZ` environment variable is NOT set, or specifies the time 
zone indirectly via reference to a filename, the standard C functions 
(on POSIX systems) are capable of using a far more flexible system to 
determine which time offset was in effect for which point in time.


Post a reply to this message

From: William F Pokorny
Subject: Re: Time for a Rant
Date: 17 Aug 2021 05:10:08
Message: <611b7cf0$1@news.povray.org>
On 8/16/21 6:45 PM, clipka wrote:
> I haven't done a good old rant lately, have I?
> 
> Well, this is the time, and this is the day.
> 
:-) At least you're still tossing jokes.

After a time... My test C/C++ file names became various obscene phrases.

If you've not found it, there is a relatively popular C++ header only 
'date.h' (and 'tz.*') for c++11/C++14/C++17. I looked at it briefly, but 
then bailed for a simpler c/unix only path.

See: https://github.com/HowardHinnant/date

My take is the license would allow POV-Ray to use it.

---
Aside: What code analysis tool is picking up the thread safe issues for 
you? I became aware these existed as I played - and I tried to handle 
them/be immune(where parser only use), but, I didn't got so far as to 
add a mutex variable & a lock guard. Suppose that would be the 
paranoid/safe approach - these time related functions are all going to 
be slow in any case - but, I didn't go that far.

Bill P.


Post a reply to this message

From: Thorsten
Subject: Re: Time for a Rant
Date: 17 Aug 2021 06:35:42
Message: <611b90fe$1@news.povray.org>
On 17.08.2021 00:45, clipka wrote:
> I haven't done a good old rant lately, have I?
> 
> Well, this is the time, and this is the day.
> 
> Speaking of which, did you know just what a clusterf*** time and date 
> related programming in C/C++ is? Or, as a matter of fact, in general?

Well, guess why a date and time function never made it into POV-Ray 
before. I am pretty sure there was a patch around 20 or so years ago for 
this, with these, and a few more problems back then...

Thorsten


Post a reply to this message

From: clipka
Subject: Re: Time for a Rant
Date: 17 Aug 2021 12:47:20
Message: <611be818$1@news.povray.org>
Am 17.08.2021 um 11:10 schrieb William F Pokorny:

> If you've not found it, there is a relatively popular C++ header only 
> 'date.h' (and 'tz.*') for c++11/C++14/C++17. I looked at it briefly, but 
> then bailed for a simpler c/unix only path.

Fun fact: "Slightly modified versions of "date.h" and "tz.h" were voted 
into the C++20 working draft at the Jacksonville FL meeting on 2018-03-17"

So it can't be too terrible.

> Aside: What code analysis tool is picking up the thread safe issues for 
> you?

That would be GitHub's CodeQL. What it actually does (among other 
things) is pick up the use of functions that are deemed inherently unsafe.

So, for instance, if I were to build a wall of mutexes and lock guards 
around the function, CodeQL would still bicker about it.

And rightly so, because even such a Fort Knox approach only works if 
there's a guarantee that the functions aren't called from anywhere else. 
So it's not the optimum approach.


Post a reply to this message

From: clipka
Subject: Re: Time for a Rant
Date: 17 Aug 2021 12:56:24
Message: <611bea38$1@news.povray.org>
Am 17.08.2021 um 12:35 schrieb Thorsten:
> On 17.08.2021 00:45, clipka wrote:
>> I haven't done a good old rant lately, have I?
>>
>> Well, this is the time, and this is the day.
>>
>> Speaking of which, did you know just what a clusterf*** time and date 
>> related programming in C/C++ is? Or, as a matter of fact, in general?
> 
> Well, guess why a date and time function never made it into POV-Ray 
> before. I am pretty sure there was a patch around 20 or so years ago for 
> this, with these, and a few more problems back then...

*Everything* was a clusterf*** of portability issues back then. Boost, 
and later C++11, took care of a lot of that.

Unfortunately, the C++ standard committee only made a half-hearted 
attempt at doing something about the date and time related stuff back then.

As a matter of fact I think C++20's functionality would make it 
reasonably easy. But for a long-lived project like POV-Ray, requiring 
C++20 now is at least half a decade too soon.


Post a reply to this message

From: Le Forgeron
Subject: Re: Time for a Rant
Date: 21 Aug 2021 07:47:15
Message: <6120e7c3$1@news.povray.org>
Le 17/08/2021 à 00:45, clipka a écrit :
> I haven't done a good old rant lately, have I?
> 
> Well, this is the time, and this is the day.
> 
> Speaking of which, did you know just what a clusterf*** time and date
> related programming in C/C++ is? Or, as a matter of fact, in general?
> 
> 

You talked too much of UTC, and forgot to mention TAI.


And if you want even more fun: GPS clock... it is yet another offset.


Post a reply to this message

From: tth
Subject: Re: Time for a Rant
Date: 21 Aug 2021 10:35:02
Message: <61210f16$1@news.povray.org>
On 8/21/21 1:47 PM, Le_Forgeron wrote:

>> Speaking of which, did you know just what a clusterf*** time and date
>> related programming in C/C++ is? Or, as a matter of fact, in general?
>>
>>
> 
> You talked too much of UTC, and forgot to mention TAI.
> 
> 
> And if you want even more fun: GPS clock... it is yet another offset.
> 
      A lot of gory details :
             http://www.catb.org/esr/time-programming/

-- 
+-------------------------------------------------------------------+
|                      sphinx of black quartz, judge my vow.        |
+-------------------------------------------------------------------+


Post a reply to this message

Copyright 2003-2021 Persistence of Vision Raytracer Pty. Ltd.