On Thu, Dec 14, 2023 at 6:23 AM Aharon Robbins <arnold(a)skeeve.com> wrote:
Hi All.
This is a bit off-topic, but people here are likely to know the answer.
tl;dr: FreeBSD retains the old timezone() function because the 4BSD series
of releases had it. Other, more modern interfaces are available, but it can
be a PITA. It's an XSI-only variable, but one of the few that FreeBSD does
not provide.
V7 had a timezone function:
char *timezone(int zone, int dst);
that returned a timezone name.
Yes. These were compile-time constants of some kind
4*60, "AST", "ADT", /* Atlantic */
5*60, "EST", "EDT", /* Eastern */
6*60, "CST", "CDT", /* Central */
7*60, "MST", "MDT", /* Mountain */
8*60, "PST", "PDT", /* Pacific */
0, "GMT", 0, /* Greenwich */
with the comment
* Sorry, I don't know all the names.
which is (a) not helpful and (b) wrong in the case of GMT (even at the time
V7 was released, the official name was UTC for the non-shifting version).
This function is only slightly changed to include a couple of more timezones
and has the warning in the man page:
This interface is for compatibility only; it is impossible to reliably
map timezone's arguments to a time zone abbreviation. See ctime(3).
This function should never be used.
BSD has had a timezone argument to gettimeofday for a long time.
It used to return the compiled-in offset from GMT(sic), but that option
has been eliminated.
The more reliable tzset() function has replaced all of that. It describes
how the TZ variable, if set, is used and where to find information about
the timezone files.
To get the local offset, you need to compare gmtime() to localtime(),
though most of the time you want to use asctime to format times, or
better, strftime(3).
There's extern char *tzname[2] that exports the timezone name(s) from
the tzcode that's the companion to what's now the IANA TZ database
(aka the olson database).
POSIX has a timezone variable which is
the offset in seconds from UTC.
It' is an optional part of POSIX, though, it's part of
XSI_C_LANG_SUPPORT: XSI General C Library
a64l( ), daylight, drand48( ), erand48( ), ffs( ), ffsl( ), ffsll( ),
getdate( ), hcreate( ), hdestroy( ),
hsearch( ), initstate( ), insque( ), jrand48( ), l64a( ), lcong48( ),
lfind( ), lrand48( ), lsearch( ),
memccpy( ), mrand48( ), nrand48( ), random( ), remque( ), seed48( ),
setstate( ), signgam,
srand48( ), srandom( ), strptime( ), swab( ), tdelete( ), tfind( ),
timezone, tsearch( ), twalk( )
So properly, should only be visible when XSI has been requested (or
when everything has been requested).
The man pages for all of {Net,Free,Open}BSD seem to indicate that both
are available on those systems.
timezone, the variable, isn't available on FreeBSD. It's not declared
anywhere.
Only timezone, the massively obsolete compatibility function is defined in
time.h. I believe neither is the 'daylight' variable.
My question is, how? The declarations for both are
given as being in
<time.h>.
But don't the symbols in libc.a conflict with each other? How does a
programmer
on *BSD choose which version of timezone they will get?
Generally, the programmer should choose to use other, more modern
interfaces. :)
timezone, the function, is about useless. To get the offset, you need to
get the
current time (or the time you are interested in) as a time_t. You'd then
call
localtime with that time_t to get a struct tm and them timegm with that tm
to get localtime as a time_t. Subtract the original time from the result to
get seconds
west of UTC.
Arguably BSDs should just support the timezone variable, but that's hard
when there's
also a function. You'd likely want it more often than the function, but you
also want old
code that's referenced it to work too. The code is there, butdisabled in
tzconfig.h due
to the conflict.
Feel free to reply privately.
Thanks,
Arnold