Bryan, this is not going to fly.
First, localtime() is not MT-safe. So you will need to use localtime_r().
But you can't use TZ like that. There is only one environment per process. Different threads can call putenv() without stepping on each other. But the last thread to change TZ wins. This is spelled out in the
putenv man page: "These functions examine and modify the environment list, which is shared by all threads in a program."
The effect of TZ is to set some variables by indirectly invoking tzset(). I thought about bypassing tzset(), but it says
here: "The ctime_r(), localtime_r(), and tzset() functions are MT-Safe in multithread applications, as long as no user-defined function directly modifies one of the following variables: timezone, altzone, daylight, and tzname. These four variables are not MT-Safe to access."
Maybe you can arrange for one process per time zone? Or write your version of localtime() that uses no per-process data?
I suppose that this sequence would work:
pthread_mutex_lock()
putenv()
tzset()
localtime_r()
pthread_mutex_unlock()
But I don't have enough experience with threads to know if that is as lame as it looks.
Personally, I would go with writing my own timezone routines. I know.... it's a lot of work. But it's the only path I see to a perfect result.