Now let's use the ctime API.
Similar to how we enhanced the original Send Update program, SNDUPD, and the Check Last Send program, CHKLSTSND, to incorporate a level of operational friendliness to the job at hand with SNDUPD2 and CHKLSTSND2, today we'll make comparable changes to the SNDUPD3 and CHKLSTSND3 programs. As a reminder, the task we are working on is to send an alert from one program (CHKLSTSNDx) when another program (SNDUPDx) has not successfully run in over six hours.
The change we will make is to store a human-readable form of the date and time the Send Update program last successfully run. We will create a new data area, QGPL/LSTSNDTIM4, with the following command:
CRTDTAARA DTAARA(QGPL/LSTSNDTIM4) TYPE(*CHAR) LEN(30)
The data area is created with a size of 30 bytes to accommodate a formatted local timestamp value such as Tue May 13 13:38:22 2008 plus an integer value of the current UTC time. We will format this local timestamp value using the Convert Time to Character String (ctime) API. The API documentation can be found in the C/C++ Language Run-Time manual, and the parameter list/prototype is repeated below.
char *ctime(const time_t *time);
The ctime API accepts one parameter, time, which is a pointer to data of type time_t. The "const" indicates that the API does not modify the value of this parameter. The ctime API also returns a pointer to a char(acter) string. This character string is formatted in the manner shown previously (Tue May 13 13:38:22 2008) with the time values converted to the local time. Other APIs exist if we wanted to format the string using UTC-based time values. The character string is documented as always being 26 bytes in length with the last two bytes representing a new-line character and a null byte.
Below is an updated Send Update program, SNDUPD4, which writes the formatted timestamp and UTC value to the data area LSTSNDTIM4.
Pgm
Dcl Var(&Snd_Int) Type(*Int)
Dcl Var(&Snd_Char) Type(*Char) Stg(*Defined) +
Len(4) DefVar(&Snd_Int)
Dcl Var(&DtaAraVal) Type(*Char) Len(30)
Dcl Var(&TimeStamp) Type(*Char) Stg(*Defined) +
Len(26) DefVar(&DtaAraVal)
Dcl Var(&Snd_Time) Type(*Char) Stg(*Defined) +
Len(4) DefVar(&DtaAraVal 27)
Dcl Var(&FmtTim_Ptr) Type(*Ptr)
Dcl Var(&FmtTim) Type(*Char) Stg(*Based) +
Len(26) BasPtr(&FmtTim_Ptr)
/* Send the updates and then: */
CallPrc Prc('time') Parm(&Snd_Int)
CallPrc Prc('ctime') Parm(&Snd_Int) +
RtnVal(&FmtTim_Ptr)
ChgVar Var(&TimeStamp) Value(&FmtTim)
ChgVar Var(&Snd_Time) Value(&Snd_Char)
ChgDtaAra DtaAra(QGPL/LSTSNDTIM4) Value(&DtaAraVal)
EndPgm
As with the earlier SNDUPD3 program, SNDUPD4 first calls the time API to obtain the current UTC time. The addition from SNDUPD3 is that the ctime API is then called, passing the current UTC time value from the time API as a parameter. The ctime API returns a pointer (&FmtTim_Ptr) to a 26-byte character string representing the formatted local time equivalent of the UTC time. In the case of SNDUPD3, this character string is represented by the &FmtTim variable, which is *BASED on the returned &FmtTim_Ptr pointer variable. SNDUPD3 modifies the variable &DtaAraVal (Data Area Value) by updating the *DEFINED subfields &TimeStamp and &Snd_Time. These subfields represent the formatted local time and UTC time_t value, respectively. The data area LSTSNDTIM4 is then updated using the &DtaAraVal variable.
After running SNDUPD4, DSPDTAARA DTAARA(QGPL/LSTSNDTIM4) should now show text similar to Tue May 13 13:38:22 2008 followed by six trailing characters that may appear to be garbled. These last six characters represent the new-line character and null byte that the ctime API appended to the formatted timestamp plus the 4 bytes for the UTC time value in an integer format.
Below is the new Check Last Send program, CHKLSTSND4. This program is essentially unchanged from the earlier CHKLSTSND3 version other than having to ignore the formatted timestamp value that now precedes the UTC time value.
Pgm
Dcl Var(&Snd_Int) Type(*Int)
Dcl Var(&Snd_Char) Type(*Char) Stg(*Defined) +
Len(4) DefVar(&Snd_Int)
Dcl Var(&Cur_Int) Type(*Int)
Dcl Var(&Alert_Time) Type(*Int) Value(21600)
Dcl Var(&Delay_Time) Type(*Dec)
Dcl Var(&Status) Type(*Char) Len(1)
Dcl Var(&DtaAraVal) Type(*Char) Len(30)
Dcl Var(&Snd_Time) Type(*Char) Stg(*Defined) +
Len(4) DefVar(&DtaAraVal 27)
Loop: RtvDtaAra DtaAra(QGPL/LSTSNDTIM4) RtnVar(&DtaAraVal)
ChgVar Var(&Snd_Char) Value(&Snd_Time)
CallPrc Prc('time') Parm(&Cur_Int)
If Cond((&Cur_Int - &Snd_Int) > &Alert_Time) +
Then(Do)
SndPgmMsg Msg('Time to send alert') +
ToPgmQ(*Ext)
ChgVar Var(&Delay_Time) Value(300)
EndDo
Else Cmd(ChgVar Var(&Delay_Time) +
Value(&Alert_Time - (&Cur_Int - &Snd_Int) +
+ 1))
RtvJobA EndSts(&Status)
If Cond(&Status *NE '1') Then(Do)
DlyJob Dly(&Delay_Time)
GoTo CmdLbl(Loop)
EndDo
EndPgm
The CHKLSTSND4 program could actually be shortened by directly defining &Snd_Int over the &DtaAraVal variable and eliminating the need for the variables &Snd_Char and &Snd_Time, but I left these variables in so that the flow of the program might appear more obvious.
As with the CEE date and time APIs, there are many C run-time date- and time-related APIs beyond just the time and ctime APIs we have looked at. I encourage you to review these additional APIs so that you can be better aware of what tools are available to you when working with time on the system. As you can see, these APIs can greatly simplify your development efforts when you want to manipulate various time values.
More CL Questions?
Wondering how to accomplish a function in CL? Send your CL-related questions to me at
LATEST COMMENTS
MC Press Online