environment independent time functions...

Christos Zoulas christos at zoulas.com
Thu Sep 30 20:35:55 UTC 2010


What I want to achieve is to be able to use the time functions in a
multi-threaded program that can handle multiple timezones at the same
time. Right now, this is impossible, because the notion of timezone is
expressed through the environment. I was careful to re-use the existing
code and not change existing functionality so the following routines
are just an add-on.

I modified tzcode 2010l to add the following functions (as defined in

First I expose an opaque timezone type:

    typedef struct __state *timezone_t;

which is no other than the internal state.

Then I provide a way to allocate the handle on per timezone name and to
free it.

    const timezone_t	tzalloc(const char *);
    void		tzfree(const timezone_t);

Note that the handle is const, because I might want to enhance this in
the future to use reference counting instead of allocating a new one
per invocation.

Then I provide a way to return the two (dst and nondst) strings (like
tzname[0], and tzname[1]) with:

    const char *	tzgetname(const timezone_t, int);

The following functions are also provided, which are like the _r counterparts
only they have an extra timezone argument:

    struct tm *	localtime_z(const time_t *, struct tm *, const timezone_t);
    char *		ctime_z(const time_t *, char *, const timezone_t);
    time_t		timelocal_z(struct tm *, const timezone_t);
    time_t		mktime_z(struct tm *, const timezone_t);
    time_t		time2posix_z(time_t, const timezone_t);
    time_t		posix2time_z(time_t, const timezone_t);

The changes to the source are minimal (the diffs are slightly larger
because I made things use ansi prototypes and removed 'register '.
I don't care about the names or the signatures much, just something
I came up as a proof of concept. Here's example code:

    #include "timeextra.h"
    #include <stdlib.h>
    #include <stdio.h>

    main(int argc, char *argv[])
	    size_t i;
	    char buf[60];
	    time_t t = time(NULL);
	    timezone_t *tz = malloc(argc * sizeof(*tz));
	    for (i = 1; i < argc; i++) {
		    tz[i] = tzalloc(argv[i]);
		    if (tz[i] == NULL)
			    err(1, "Cannot find timezone %s", argv[i]);
	    for (i = 1; i < argc; i++) {
		    printf("[%s] [%s] %s", tzgetname(tz[i], 0),
			tzgetname(tz[i], 1),
			ctime_z(&t, buf, tz[i]));
	    return 0;

Has anyone done this work or similar?
Do you think others might want something like this?
Are you interested in taking a look at the changes/incorporating them?
Do you have any other suggestions?

Best Regards,


More information about the tz mailing list