Today, we'll look at more uses for the Convert Date and Time Format API.
Last month, in How Do You Want That Date and Time?, we used the first five parameters of the Convert Date and Time Format (QWCCVTDT) API to format a date and time value stored in a *DTS format to a YYYYMMDDHHMMSS format that's much friendlier to work with. This month, we'll look at the two optional parameter groups of the API. But first some background.
One of the companies I work with supports multiple plants on the same system, with not all of the plants necessarily being in the same time zone. They, however, want to provide date and time values on various panels and reports in the local time zone of the plant a user is associated with. They in the past have done this by storing a time zone offset value in each plant library. So, for instance, if the system is in Mechanicsburg, Pennsylvania, then facilities in New York would have an offset value of 0, facilities in Amarillo, Texas, would have an offset value of -1, and so on. When an application needs the current date and time, it simply calls a common function and the function accesses the system local time and then adjusts it based on the offset found in the plant library. This approach is fast and works quite well in a Monday thru Friday (or Saturday) 8 to 5 environment, but only 99.97+% of the time in a 24x7 environment. For instance, this past March 8, Amarillo reported a problem—namely, that times such as 1:15 a.m. were showing up as being 2:15 a.m. This problem was due to March 8, 2015, being the start of Daylight Saving Time (DST) in the United States. At 2:00 a.m., Mechanicsburg local time moved forward by one hour to 3:00 a.m., causing the Amarillo calculation to take a local system time of say 3:15 a.m., add an hour offset value of -1, and then return 2:15 a.m.. The problem went away after 60 minutes when Amarillo also started DST at 2:00 a.m. local time.
The optional parameter groups of the QWCCVTDT API allow you to correctly (100% of the time rather than 99.97+% of the time) convert date and time values from one time zone to another. Optional parameter group one defines five parameters.
The first optional parameter is the input time zone. This is a Char(10) input value that defines the time zone associated with the time value provided in required parameter number two if the special value *CURRENT is not being used for the first required parameter. In addition to supporting the name of a time zone (*TIMZON) object, the API also supports the special values of:
- *SYS to interpret the input value as being in the time zone specified by the QTIMZON system value. This is the default value if the parameter is not passed to the API.
- *UTC to interpret the input time value as being a Coordinated Universal Time (UTC) value.
- *JOB to interpret the input time value as being in the time zone specified by the time zone job attribute.
The second optional parameter is the output time zone. This parameter identifies the time zone you want the returned output value of required parameter four to be in. The parameter is defined the same as the first optional parameter and supports the same list of special values.
The third and fourth optional parameters allow you to also retrieve information about the time zone identified by the second optional parameter (the output time zone). The third parameter is a variable-length receiver variable where the API can return information such as the name of the time zone used, whether or not the time zone is currently in DST, and the full name of the time zone. The fourth optional parameter is a Bin(4) input value providing the length of the receiver variable. A value of 0, which is what we'll be using, indicates that no time zone information is to be returned to the application.
The fifth optional parameter is a Char(1) input value indicating the precision of the input and output values (required parameters two and three), respectively. A value of '0' indicates that the values have a precision in milliseconds, a value of '1' that the values have a precision of microseconds.
With that introduction, the following program (CvtDat2) calls the QWCCVTDT API twice and dsplys the resulting local current times for Mechanicsburg and Amarillo, respectively. The time zone for Mechanicsburg is QN0500EST3 and the time zone for Amarillo QN0600CST2. The WRKTIMZON command can be used to see what all time zones are defined for your system and what DST rules are defined, if any, for the various time zones.
h dftactgrp(*no)
d CvtDat2 pr
d CvtDat2 pi
****************************************************************
d CvtDatTim pr extpgm('QWCCVTDT')
d InpFmt 10a const
d InpValue 20a const options(*varsize)
d OutFmt 10a const
d OutValue 20a options(*varsize)
d ErrCde likeds(QUSEC)
d InpTZ 10a const options(*nopass)
d OutTZ 10a const options(*nopass)
d TZInfo 1a const options(*nopass)
d LenTZInfo 10i 0 const options(*nopass)
d PrecInd 1a const options(*nopass)
d InpTimInd 1a const options(*nopass)
****************************************************************
d YYMDValue s 20a
****************************************************************
/copy qsysinc/qrpglesrc,qusec
****************************************************************
/free
CvtDatTim('*CURRENT' :' '
:'*YYMD' :YYMDValue :QUSEC
:' ' :'QN0500EST3'
:' ' :0 :'0');
dsply (%char(%date(%subst(YYMDValue :1 :8) :*ISO0)) + ' ' +
%char(%time(%subst(YYMDValue :9 :6) :*HMS0)));
CvtDatTim('*CURRENT' :' '
:'*YYMD' :YYMDValue :QUSEC
:' ' :'QN0600CST2'
:' ' :0 :'0');
dsply (%char(%date(%subst(YYMDValue :1 :8) :*ISO0)) + ' ' +
%char(%time(%subst(YYMDValue :9 :6) :*HMS0)));
*inlr = *on;
return;
// ************************************************************
begsr *inzsr;
QUSBPrv = 0;
endsr;
/end-free
Calling the program results in the following messages:
DSPLY 2015-07-12 07.07.45
DSPLY 2015-07-12 06.07.45
The messages indicate that it is currently 7:07 a.m. on July 12, 2015, in Mechanicsburg (or more properly in the Eastern Time Zone) and 6:07 on July 12 in Amarillo (or really anywhere in the Central Time Zone).
We'll now "pretend" it's 3:15 a.m. in Mechanicsburg by changing the two API calls to the following:
CvtDatTim('*YYMD' :'20150308031500000'
:'*YYMD' :YYMDValue :QUSEC
:'QN0500EST3' :'QN0500EST3'
:' ' :0 :'0');
dsply (%char(%date(%subst(YYMDValue :1 :8) :*ISO0)) + ' ' +
%char(%time(%subst(YYMDValue :9 :6) :*HMS0)));
CvtDatTim('*YYMD' :'20150308031500000'
:'*YYMD' :YYMDValue :QUSEC
:'QN0500EST3' :'QN0600CST2'
:' ' :0 :'0');
dsply (%char(%date(%subst(YYMDValue :1 :8) :*ISO0)) + ' ' +
%char(%time(%subst(YYMDValue :9 :6) :*HMS0)));
Now, calling the program results in the following messages:
DSPLY 2015-03-08 03.15.00
DSPLY 2015-03-08 01.15.00
This shows that it is currently 3:15 a.m. on March 8, 2015, in Mechanicsburg and 1:15 a.m. on March 8 in Amarillo. Note that the Amarillo local time is now correct.
We do still have a potential problem though, and that is when DST ends. In 2015, come November 1, the Mechanicsburg local time at 2:00 a.m. will fall back to 1:00 a.m. so there will be two instances of the time range 1:00 a.m. to 2:00 a.m. In the first instance of 1:15 a.m. for Mechanicsburg, the Amarillo local time is 00:15 a.m. while in the second instance of 1:15 a.m. it will also be 1:15 a.m. Amarillo time. How does the QWCCVTDT API know which instance (the first or second) is to be used when processing the input time value? First, the good news: if we're using the input time value of *CURRENT, the system will take care of this for us. But if we are providing a discrete value, as we are in the previous example when specifying '20150308031500000', then there are a couple of ways to handle this.
One approach is with the second optional parameter group of the QWCCVTDT API. Optional parameter group 2 defines one parameter. A Char(1) Input time indicator that, when set to '0', means we are in the second (or Standard Time) instance and if '1' we are in the first (or DST) instance. The default is '1'. This is one of the pieces of information available to you with the third and fourth parameters of optional parameter group 1.
The second approach, and the one I prefer, is to simply not use an input time zone that observes DST when working with discrete values. There are several such time zones on the system, with Q0000UTC being one, and in the case of QWCCVTDT, there is support for the special value *UTC as a time zone so you don't even have to remember the *TIMZON object name.
We can change our two calls to QWCCVTDT to use *UTC based values:
CvtDatTim('*YYMD' :'20151101051500000'
:'*YYMD' :YYMDValue :QUSEC
:'*UTC' :'QN0500EST3'
:' ' :0 :'0');
dsply (%char(%date(%subst(YYMDValue :1 :8) :*ISO0)) + ' ' +
%char(%time(%subst(YYMDValue :9 :6) :*HMS0)));
CvtDatTim('*YYMD' :'20151101051500000'
:'*YYMD' :YYMDValue :QUSEC
:'*UTC' :'QN0600CST2'
:' ' :0 :'0');
dsply (%char(%date(%subst(YYMDValue :1 :8) :*ISO0)) + ' ' +
%char(%time(%subst(YYMDValue :9 :6) :*HMS0)));
Now, results in the two messages:
DSPLY 2015-11-01 01.15.00
DSPLY 2015-11-01 00.15.00
The API is returning the correct local times for the first instance of 1:15 a.m. in Mechanicsburg. Changing the discrete value '20151101051500000' to '20151101061500000' (adding one hour so that we're in the second instance of 1:15 a.m. in Mechanicsburg) results in the correct values of:
DSPLY 2015-11-01 01.15.00
DSPLY 2015-11-01 01.15.00
And adding yet another hour ('20151101071500000') to the UTC time value results in the local times of:
DSPLY 2015-11-01 02.15.00
DSPLY 2015-11-01 01.15.00
Amarillo is now on Standard Time and seeing the second instance of 1:15 a.m..
Using the QWCCVTDT API, and its time zone support, enables the correct representation of local times in a distributed environment and does not require you to personally handle the various quirks of DST. In the case of our original problem—the storing of an appropriate numeric offset value (0 for Mechanicsburg, -1 for Amarillo) per plant—we could change to storing the appropriate *TIMZON object name for the plant, use the API, and be done with it (with 100% accuracy).
Have Some System API Questions?
As usual, if you have any API questions, send them to me at
LATEST COMMENTS
MC Press Online