struct tm, timegm()/timelocal() & TZ fiddling (programmatically)

struct tm, timegm()/timelocal() & TZ fiddling (programmatically)

Post by Guy Harr » Sat, 21 Mar 1992 07:43:47



Quote:>Do these functions pay any attention at all to the:

>     int tm_isdst;    /* 1 if DST in effect */
>     char *tm_zone;   /* abbreviation of timezone name */
>     long tm_gmtoff;  /* offset from GMT in seconds */

>fields of the struct tm handed to them?

No.  "mktime()" - which is also in SunOS 4.1[.x] (although not in
4.0[.x]), and is the official ANSI C standard interface for this - does
pay attention to "tm_isdst", for reasons that are, I think, somewhat
bogus.  However, "timelocal()" and "timegm()" do not.

None of the three routines pay any attention whatsoever to "tm_zone" or
"tm_gmtoff".

Quote:>Is the programmer expected to
>track whether the value in the struct tm represents some local time
>(correlated to current [non]-setting of TZ) or do these functions
>attempt to use the values in the above fields?

The programmer is expected to use "timelocal()" only to convert local
times, in the time zone specified by the current [non-]setting of TZ, to
UNIX times, and is expected to use "timegm()" only to convert time
specifications for UTC into UNIX times.

The programmer is *also* not expected to stuff anything into "tm_zone"
nor "tm_gmtoff", and is not expected to stuff anything into "tm_isdst"
before a call to "timelocal()" or "timegm()"; the programmer should
stuff -1 into "tm_isdst" before calling "mktime()" - -1 says "I don't
know if it's DST or not, *you* tell *me* whether it is".

(The programmer is *NOT* expected to know whether the time in question
is during Daylight Savings Time or not; take a look at some of the
source files in "/usr/share/lib/zoneinfo", and ask yourself whether you
*WANT* your software to have to worry about the quirks of N legislatures
throughout the world - that's the whole reason Arthur Olson and the rest
of the Timezone Caballeros came up with that software in the first
place....)

If the programmer wishes to convert times for some arbitrary time zone,
they are expected to set the environment variable TZ to the appropriate
value for that time zone, call "tzset()", and then convert the time.

Quote:>How do I do the equivalent of an unsetenv TZ programmatically?

March through the environment by hand and rip any TZ setting out of it.

Quote:>Am I stuck _requiring_ that TZ be set to something upon program
>startup?

No, because you can either rip TZ out of the environment by hand, or do:

        putenv("TZ=localtime");

which has the same effect.  ("localtime" here means the string beginning
with the letter 'l', followed by the letter 'o', followed by... i.e.,
it's not a place-holder for the current time zone, it's the string
"localtime".)

 
 
 

struct tm, timegm()/timelocal() & TZ fiddling (programmatically)

Post by Robert E » Sat, 21 Mar 1992 07:44:34



>The man page [ctime(3)] states for these functions that:
>     timelocal() and timegm() convert the time specified  by  the
>Do these functions pay any attention at all to the:
>     int tm_isdst;    /* 1 if DST in effect */
>     char *tm_zone;   /* abbreviation of timezone name */
>     long tm_gmtoff;  /* offset from GMT in seconds */

No.  Only the ones that actually specify the date/time (tm_wday and tm_yday
are also meaningless).

Quote:>Is the programmer expected to
>track whether the value in the struct tm represents some local time
>(correlated to current [non]-setting of TZ) or do these functions
>attempt to use the values in the above fields?

The former.  For convertions to/from "local" time, the
current local timezone (from TZ initially) is assumed.
If you have enough information to set the other fields
(is_dst and gmtoff) then you could just make the adjustment yourself
and use timegm() instead of timelocal().   But that's not easy...

Quote:>In order to be able to convert the date/time values passed in on the
>data stream, I planned to reduce the input value to a struct tm, stash
>current setting of TZ [via getenv(3)], set TZ to input stream TZ [via
>putenv(3)] perform conversion [time_t gmval = gmtime(timelocal(struct
>tm *inval))], and then restore TZ [via putenv(3) again].  

Don't forget to tzset() after the change to TZ, or your changes will have
no effect..

Quote:>Problem:
>what if application environment doesn't have TZ set in the first
>place?  ...
>How do I do the equivalent of an unsetenv TZ
>programmatically?  Am I stuck _requiring_ that TZ be set to something
>upon program startup?

No, that would be an anathema to the design of these functions.
You can just call tzsetwall() and forget what TZ is set to (which is
fine, and best, unless you're going to fork a sub-process, which would
use the incorrect value of TZ).

Or, you can set TZ to "localtime"

Or, you can just undefine TZ again, in a rather crude way (but one that
works...).  Just save the address of the last string you passed to
putenv() that set TZ, then when you want to unset it, use "buf[0] = 'Z';"
or something similar .. ie: change the 'T' that was in the string (or
the Z if you prefer) to some other chanacter - TZ is no longer set, the
other thing is...

kre

 
 
 

struct tm, timegm()/timelocal() & TZ fiddling (programmatically)

Post by resident.ali » Sat, 21 Mar 1992 04:08:47


The man page [ctime(3)] states for these functions that:

     timelocal() and timegm() convert the time specified  by  the
     tm  argument  to  a  time  value  that  represents that time
     expressed as the number  of  seconds  since  Jan.  1,  1970,
     00:00,  Greenwich  Mean Time.  

     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).

     timegm() converts a struct tm that represents GMT.

Do these functions pay any attention at all to the:

     int tm_isdst;    /* 1 if DST in effect */
     char *tm_zone;   /* abbreviation of timezone name */
     long tm_gmtoff;  /* offset from GMT in seconds */

fields of the struct tm handed to them?  Is the programmer expected to
track whether the value in the struct tm represents some local time
(correlated to current [non]-setting of TZ) or do these functions
attempt to use the values in the above fields?

A related issue:  I have a program that takes possibly multiple streams
of input, each of which may be from a different location.  A value in
each data stream may be a date/time value.  We have a requirement in
our applications that all input values are converted from local "units"
to system-base "units" upon entry.  In this case, we use UTC as the
base notation for date/time values.  Each individual input stream may
be from a different time zone.  We can set up the configuration of the
application so that the TZ of each input stream is named explicitly.

In order to be able to convert the date/time values passed in on the
data stream, I planned to reduce the input value to a struct tm, stash
current setting of TZ [via getenv(3)], set TZ to input stream TZ [via
putenv(3)] perform conversion [time_t gmval = gmtime(timelocal(struct
tm *inval))], and then restore TZ [via putenv(3) again].  

Problem:
what if application environment doesn't have TZ set in the first
place?  Default behaviour on Sun's is to use system's notion of local
time zone if TZ is undefined.  However, as soon as I define TZ via
putenv(), the only option I have to undefine it is to putenv("TZ=");
The result of that on subsequent calls to timelocal() and localtime()
is to produce GMT!  How do I do the equivalent of an unsetenv TZ
programmatically?  Am I stuck _requiring_ that TZ be set to something
upon program startup?

--

DRD Corp., 5506 South Lewis Ave., Tulsa, OK 74105         (918)745-9037 fax

 
 
 

1. setting up struct tm when calling timelocal

In SunOS 4.x, when I call timelocal, I generally set the first
six fields of the struct tm:

        int     tm_sec;
        int     tm_min;
        int     tm_hour;
        int     tm_mday;
        int     tm_mon;
        int     tm_year;

I leave the following uninitialized:

        int     tm_wday;
        int     tm_yday;
        int     tm_isdst;
        char    *tm_zone;
        long    tm_gmtoff;

I noticed that Purify gives UMC errors (uninitialized memory copy)
in timelocal, indicating that maybe some library code is looking at one
of the last five elements of the tm.  Is there any reason to set these
elements or are they strictly 'out' values returned by timelocal.

David Blackman

--

David Blackman

(215) 496-6760

2. Linux & Motif

3. Solaris 2.1 seems to be missing timegm() and timelocal()

4. No login on serial console after new 4.3 install

5. Time functions strptime, timelocal, timegm

6. remsh C program will not display output

7. struct tm & GMT query

8. Need help determining best chipsets to use for Linux RH 5.0

9. mktime alternative that creates a GMT 'struct tm' ???

10. Converting struct tm to time_t

11. times() struct tms

12. hrtime_t - convert to -> struct tm

13. tms_stime in struct tms