[comp.unix.questions] UNIX time and the parent environment

pvo3366@neptune.uucp (Paul O'Neill) (08/29/89)

I am digitizing video tapes with an image processor in a Sun 4/110, SunOS 4.0.1.

In the header to the time series that I'm producing I want to have the following
2 numbers:

	data_start_time = number of seconds since Jan. 1, 1970, 00:00, GMT
			  (when the video started)

	dgtz_start_time = number of seconds since Jan. 1, 1970, 00:00, GMT
			  (when the digitizing started)

It's easy enough for the digitizing program to prompt the user for enough
data to fill in a skeleton struct tm.  timelocal(3) then seems to be the
way to go to get the time_t (# of seconds since ....).

THE PROBLEM:  The tapes are usually recorded in a different time zone than
	      they are digitized in.

Nominally timelocal(3) grabs the local time zone for the conversion 
-- this works.

If environmental variable TZ is set to a valid zoneinfo path (something in 
/usr/share/lib/zoneinfo), timelocal(3) grabs this time zone for the 
conversion -- this works.

If TZ exists, but is unset, timelocal(3) converts as if time zone = GMT
-- this works.

But I need to do 2 timelocal(3) calls in the same program, each with a 
different time zone.

I can successfully call getenv(3) and manipulate what's at the returned 
address.  I can also successfully call putenv(3) and set TZ that way.  But
timelocal(3) doesn't pay any attention to the environment I've manipulated in
this way.  It insists on using the parent shell's idea of TZ.

Manually filling in the struct tm's .tm_zone and .tm_gmtoff doesn't work either,
because timelocal(3) overwrites them during the call with what it thinks
they should be to match the parent's TZ.

THE QUESTION: Why doesn't timelocal() use the environmental variable I'm
manipulating?  Is there a way to get it to sit up and take notice?  How do 
I do multiple yr/mo/da/hr/min/sec -> time_since_the_epoch conversions in 
multiple time zones?

Thanks. (This is driving me nuts!)


Paul O'Neill                 pvo@oce.orst.edu
Coastal Imaging Lab
OSU--Oceanography
Corvallis, OR  97331         503-754-3251

guy@auspex.auspex.com (Guy Harris) (08/30/89)

>THE QUESTION: Why doesn't timelocal() use the environmental variable I'm
>manipulating?

Because you haven't told it to.

>Is there a way to get it to sit up and take notice?

Yes.  From the 4.0.1 CTIME(3) (presented out of order):

     "tzset()" uses the value of the environment variable TZ  to  set
     time  conversion  information used by "localtime()".

	...

     ..."timelocal()" converts a "struct tm" that represents local time,
     correcting for the time  zone and  any  time  zone  adjustments
     (such as Daylight Savings Time).  Before doing so, "timelocal()"
     calls "tzset()"  (if "tzset()" has  not been called in the current
     process).

The key part is "if 'tzset()' has not been called in the current
process".  Basically, "timelocal()" does not check TZ every time; by and
large, it assumes it's already been checked.  It only checks it if it
knows that it has not been checked. 

"tzset()" is the routine that actually checks TZ.  If you explicitly
call it, it throws out any data it constructed from any previous
invocation, and reconstructs it given the new setting of TZ.

I expect this to be true of any UNIX system with "tzset()", including
System V - no, System V, as currently distributed by AT&T, doesn't have
"timelocal()", but it *does* have "localtime()" (as anything worthy of
the name "UNIX" does), and "localtime()"'s behavior is also affected by
TZ.  Furthermore, S5R4 should have the ANSI C "mktime()" routine, which
is almost like "timelocal()", and which should be affected by TZ as
well.  (SunOS 4.1 should also have "mktime()"; since it's in the ANSI C
standard, it should in the future be used in preference to
"timelocal()".)

Thus, in any UNIX system supporting TZ (and, in fact, any POSIX
1003.1-compliant system, all of which must support TZ), a program should
call "tzset()" after changing TZ in the environment of the process in
which it's running.