use of global variables in time data.

Alf Salte alf.salte at comvie.no
Wed Oct 3 11:41:22 UTC 2007


Now, don't get me wrong. We probably have to live with global variables
in association with time for a long time - not the least because of
backwards compatibility.

However, I do feel that a more "object oriented" approach would be
superior and wonder how hard it would be to make a rewrite of parts of
the code so that one could provide such an interface. It would be
particularly useful for languages like C++ etc but would also be useful
for C as C too can handle object oriented type features as is handled in
FILE etc.

What I mean by object oriented approach here is not full fledged OOP - C
is not an OO language. What I mean is simply that you can create an
object that represent something and then reference that object to refer
to that something later and then destroy it when no longer needed.

With this in mind I would like a timezone_t type so that you could do
something like:

timezone_t * tzNY = tzmake("US/Eastern"); // EDT/EST timezone
timezone_t * tzUTC = tzmake("Universal"); // or just mktz("")
timezone_t * tzlocal = tzmake(NULL);

Then you could do stuff like:

struct tm nyTime, gmTime, localTime;
time_t now;

now = time();
tztime(& nyTime, & now, tzNY);

// would do the same as gmtime().
tztime(& gmTime, & now, tzUTC);

// would do the same as localtime().
tztime(& localtime, & now, tzlocal):

// The last one could also be achieved by:
tztime(& localtime, & now, NULL);

tzrem(tzNY);
tzrem(tzUTC);
tzrem(tzlocal);

-----------------

The existing approach appear simple enough but the problem is that
tzset() has the following deficiencies as I see it:

1. It always only operate through TZ variable - would be nice if there
was a version that took the data as string so that tzset() could
essentially be implemented by calling that function with getenv("TZ") as
argument.

2. It leaves the result in various global variables which are defined
around the code. Would be nice if the function instead created a struct
and kept all data that is to survive the function call within that
struct.

3. For backwards compatibility then tzset() should essentially do the
folowing:

void tzset(void)
{
	struct timezone_t * tzi = tzmake(getenv("TZ"));
	// copy data from tzi to various global variables.
	// timezone, altzone, daylight and tzname etc.
	// details of this depends on exactly what data
	// are stored in timezone_t
	// This could also be placed in a separate function
	// so user can set these variables based on a
	// previously generated tzmake() call.
	tzsettz(tzi);
	tzrem(tzi);
}

How much work would it take to do such a rewrite? After browsing the
source I find that there are numerous global variables between tzset.c
and tzfile.c that are not documented anywhere but still are used such as
tz_rules and __use_tzfile just to name two of them.

Also, if some applications want to avoid allocation of data one could
have a version that took the timezone_t struct on input and filled it
in. The problem here is how to handle timezone strings. However,
assuming that timezone strings are usually small (3-5 letters max for
strings like UTC, CEDT, etc.) one could define that timezone_t has
allocated say 8 bytes for each of the strings so that it is fixed size.
Then one could:

struct timezone_t tzUTC;

tzmake(& tzUTC, "Universal");

instead of the
tzUTC = tzmake("Universal");

I wrote above. In this case the tzrem() function would not be necessary.

Yet again both approaches would be possible where tzmake first malloc()
a struct large enough to hold the data and then called the other version
to fill in the struct. IN this case tzrem would still be needed and you
would need two different versions of tzmake().

For example:

timezone_t * tzcreate(getenv("TZ"));

which was implemented as:

timezone_t * tzcreate(const char * tzid)
{
	timezone_t * res = malloc(sizeof(timezone_t));
	if (res == NULL)
		return NULL;
	tzmake(res,tzid);
	return res;
}

Finally, and not really related to the above. I am trying at the moment
to read and understand the code. I notice that the tzfile is opened with
"rc" mode. I am not sure exactly what the "c" letter there indicates. It
says something about prohibiting cancelattion but I am not exactly sure
what that means in practice. Is it that if user interrupts the process
while in the middle of say reading the file the interrupt will be
waiting until the file is closed or what?

Alf





More information about the tz mailing list