Controlling z/OS timezones for Language EnvironmentⓇ applications
Target Audience
Anyone running applications under z/OS that use IBM Language Environment services and who needs customised control of timezone decoding on a per-job basis.
Introduction
The timezone displayed by a z/OS system, and the date and time when it moves from winter time to summer time, and back again, is controlled by a number of different parameters in different parts of the parmlibs structure, depending on exactly which function is called, and these, of course, have global effect.
You may, however, have a need for more localised control. This might be:
For testing of new definitions
For processing data requiring different timezone settings than your system defaults
For processing historical data which used different settings to those currently in effect
Because your systems’ settings are not correct and can’t be changed.
If any of the various proposed laws in the USA1 and EU2 ever come to fruition, this may become of some importance.
Indeed, running the IBM z/TPF IPTPRP IP Trace utility recently, I found I needed a different timezone definition to the one which was in effect on my system.
So what do you do if you need run an application using a different timezone, or summer time definition, from those used system wide?
First of all you need to determine which system services the application is calling to perform the decoding, which may require checking the source code. In my case, it was an IBM Language Environment function.
The actual format of the POSIX TZ parameter is well known, and fully documented, for example here. What is less clear is how this can be changed for a single application. It turns out that it is truly well buried in the IBM documentation, even more so than usual, but it can be done. There’s even two ways, both of them pretty straightforward.
In the PARMs
This is the simplest way. Just wrap the definition in an ENVAR(), and put it at the start of the PARMs, then separate it from the normal parameters for your program using a slash. Everything after the slash will be passed on to the program as usual, for example:
//XXXX EXEC PGM=XXXX,
// PARM=('ENVAR("_TZ=CET-1CEST,M3.5.0/2,M10.5.0/3")',
// '/... normal parameters ...')
// ...
You may have to use the environment variable TZ rather than _TZ depending on if your system is configured with POSIX(ON) or POSIX(OFF). If you’re not sure, ask your z/OS systems programmer, or just try and see which one works.
The gotcha here, of course, is that the total PARM field cannot exceed 100 bytes so, unless your program’s needs are rather simple, you’re likely to run out of room.
In a DD
The alternative is to put the ENVAR() in a CEEOPTS DD, which works just as well, and allows the full use of the 100 bytes PARM field. Here it is, inline:
//XXXX EXEC PGM=XXXX
//CEEOPTS DD *
ENVAR("_TZ=CET-1CEST,M3.5.0/2,M10.5.0/3")
/*
//*
// ...
Thanks
This article is based on work performed for SNCF, and is published with their permission, for which many thanks.