I once wrote some C code that sets the TZ, _TZ variables from the time zone offset, leap second offset values in the CVT.

#define STCK_UNIT_HOUR 0xD693A400000LLU
#define STCK_UNIT_MIN  0x3938700000LLU
#define STCK_UNIT_SEC  0xF4240000LLU

void set_time_zone(int64_t adjust) {
  char tzone[30] = "GMT";
  char sign = '+';
  int tz_offset_hours = 0;
  int tz_offset_mins = 0;
  int tz_offset_secs = 0;

  // get the time zone offset from the CVT
  const CVT * cvt = *((CVT **)CVTPTR);

  // set the time zone offset and apply the leap second offset
  int64_t ldto = cvt->cvtext2->cvtldto - cvt->cvtext2->cvtlso + adjust;

  // if the time set offset is 0 (GMT) then no need to continue. But
  // still set the time zone to GMT just in case the operator has changed
  // the system clock with a console command.
  if (ldto != 0) {
    if (ldto < 0) {
      sign = '+';    // west of the meridian
      ldto = -ldto;  // make it positive for the divide
    }
    else {
      sign = '-';   // east of the meridian
    }
    tz_offset_hours = ldto / STCK_UNIT_HOUR;
    // if minutes have been specified then calculate them
    uint64_t mins = ldto % STCK_UNIT_HOUR;
    if (mins > 0) {
      tz_offset_mins = mins / STCK_UNIT_MIN;
      // if seconds have been specified then calculate them
      uint64_t secs = mins % STCK_UNIT_MIN;
      if (secs > 0) {
        tz_offset_secs = secs / STCK_UNIT_SEC;
      }
    }
    // format the environment variable and set the time zone
    sprintf(tzone, "GMT%c%d:%d:%d",
        sign, tz_offset_hours, tz_offset_mins, tz_offset_secs);
  }

  setenv("TZ", tzone, 1);   // for POSIX
  setenv("_TZ", tzone, 1);  // for non-POSIX
  tzset();
}



On 2019-08-16 8:22 AM, Charles Mills wrote:
The Dignus runtime main() start-up from a BATCH or TSO start examines the
CVTTZ value and constructs a TZ that offers the proper offset

Good approach IMHO. I know I tried doing that and ran into some sort of
issue.

The fact is that the LE approach is poor. I don't say that because I am a
configuration genius and could have done better. I say that because in 8
years of supporting an STC written in C++ we encountered customer after
customer with whom we had the following dialog:

"Your product is broken. The times are wrong."
"You just need to set the local time offset in /etc/whatever."
"No, we have the local offset. Every other product gets it right. Your
product is broken."
"That's in CLOCKxx. You need to set the local time zone variable with ENVAR
in /etc/whatever."
"Why should we have to do that. Every other product gets it right. Your
product is broken."

The default for USS startup should be the offset in SYS1.PARMLIB(CLOCKxx),
and let UNIX-sophisticated customers override that as they wish.

Charles


-----Original Message-----
From: IBM Mainframe Discussion List [mailto:IBM-MAIN@LISTSERV.UA.EDU] On
Behalf Of Thomas David Rivers
Sent: Thursday, August 15, 2019 1:57 PM
To: IBM-MAIN@LISTSERV.UA.EDU
Subject: Re: Local time in C on z/OS

Phil Smith III wrote:

I have a C POSIX application that writes timestamps on its output. It's
always produced a GMT timestamp (pardon me, UTC), and that's sort of fugly,
so I thought maybe I could fix it.

The fundamental problem with "local time" is the definition of "local".

If we make the assumption that the machine clock is kept in UTC (GMT), then
the local time is simply the different from UTC to where one might be at
that
moment on the globe.

Now - consider the problem of a terminal connected to a fairly remote
system.
The user may consider himself in a different timezone from the system; hence
his idea of "local" is different than the, say, the operator console
which happens
to be physically adjacent to the actual hardware device that keeps track
of the
time.

This is why UNIX/POSIX has the TZ environment variable - one user can set a
different timezone than another.   And this is also why a "global"
setting of
TZ in, say, /etc/rc isn't always the right idea.  You may have multiple
users in
multiple timezones.

Some systems might go as far as keeping a database of sorts for
terminals, and
having the /etc/rc script make a good guess as to what the proper TZ setting
might be.

This is also why the ssh (and other remote-connect-over-the-internet
protocols)
have mechanisms for passing the value of the TZ environment variable to the
remote shell.   The user connecting can say "hey - when you connect, set
this
to be my TZ value."

All that is well and good - but then we run into the problem of programs
being
dub'd without going thru the typical UNIX start-up... what TZ should
they get then?

The Dignus runtime main() start-up from a BATCH or TSO start examines
the CVTTZ
value and constructs a TZ that offers the proper offset from UTC (again,
this assumes
the machine's clock is set to UTC and that CVTTZ is properly set.)
This basically
gives you a "local time" for the machine, the user would need to set TZ
to something
else if they are not in the same locality as the machine.   Under a USS
start-up, we
inherit the TZ environment variable from the BPX environment.

Thus - the entire question about "what time is it" is totally answered
when you
can reliably answer the question of "where are you?"

     - Dave Rivers -




----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN

Reply via email to