Find Time and Date Durations in RPG
December 8, 2010 Hey, Ted:
Time and date calculations fall short in ILE RPG. I have seen many examples of handling date or time math on IT Jungle and other Web sites. All of them calculate one unit of time only–either years, days, hours, minutes, etc. In the application I am working on, I need to find an interval in days, hours and minutes, but I have found nothing that subtracts one date from another and gets a true answer in mixed units.
RPG does not have date and time durations, as SQL and Query do. (For more information about durations, see the articles listed below.) You’ll have to write your own solution, Al, but it isn’t difficult.
Write a subprocedure that accepts two timestamp values and returns whatever units you need. Take a look at the source code for module TIMEDIFF. This module contains a subprocedure named CalcTimeDiff (calculate time difference), which calculates elapsed times in days, hours and minutes.
H nomain H option(*srcstmt) /copy prototypes,TimeDiff P CalcTimeDiff b export D CalcTimeDiff pi D Time1 z value D Time2 z value D ElapsedDays 3p 0 D ElapsedHours 3p 0 D ElapsedMins 3p 0 /free ElapsedDays = %diff(Time1: Time2: *days); if ElapsedDays > *zero; Time1 -= %days(ElapsedDays); endif; ElapsedHours = %diff(Time1: Time2: *hours); if ElapsedHours > *zero; Time1 -= %hours(ElapsedHours); endif; ElapsedMins = %diff(Time1: Time2: *minutes); return; /end-free P e
Here’s the procedure prototype, also called TIMEDIFF, but stored in source physical file PROTOTYPES.
D CalcTimeDiff pr D inTime1 z value D inTime2 z value D ouElapDay 3p 0 D ouElapHour 3p 0 D ouElapMinute 3p 0
Use Create RPG Module (CRTRPGMOD) to create a module from the RPG source code.
CRTRPGMOD MODULE(MYLIB/TIMEDIFF) SRCFILE(MYLIB/QRPGLESRC) SRCMBR(TIMEDIFF)
Leave it as a module or convert the module to a service program, according to your preference.
I threw together an example calling program. First, here’s a printer file for a job history report.
A REF(JOBHIST) A R HEADER SPACEB(1) A 2'Job No' A 9'WkCtr' A 15'Start date/time' A 35'End date/time' A 55'Days' A 61'Hrs' A 65'Mins' A R DETAIL SPACEB(1) A JOBNO R 1 A WORKCTR R + 1 A DATEON R + 1 A TIMEON R + 1 A DATEOFF R + 1 A TIMEOFF R + 1 A ELAPDAY 3S 0 + 1EDTCDE(M) A ELAPHOUR 3S 0 + 1EDTCDE(M) A ELAPMIN 3S 0 + 1EDTCDE(M)
Here’s the RPG program that reads the job history file and builds the report. Notice the call to CalcTimeDiff.
H option(*srcstmt: *nodebugio) Fjobhist if e k disk Fqad0421p o e printer /copy prototypes,TimeDiff /free *inlr = *on; write Header; dow '1'; read jobhistr; if %eof(); leave; endif; CalcTimeDiff ( %date(DateOff: *iso) + %time(TimeOff: *hms): %date(DateOn: *iso) + %time(TimeOn: *hms): ElapDay: ElapHour: ElapMin); write Detail; enddo; return; /end-free
And here’s the report. Notice the elapsed time–in days, hours, and minutes–between job-on and job-off in the last three columns.
Job No WkCtr Start date/time End date/time Days Hrs Mins 56882 A1010 2010-12-01 8:22:55 2010-12-01 8:24:13 1 56883 A1020 2010-12-01 8:30:14 2010-12-01 11:18:32 2 48 56884 B2050 2010-12-01 8:12:14 2010-12-02 15:54:03 1 7 41 56885 B2085 2010-12-01 9:01:02 2010-12-01 9:25:09 24 56886 A1340 2010-12-01 9:01:02 2010-12-01 8:50:16 10-
The nice thing about ILE is that you don’t have to wait for IBM to add an opcode to the compiler to implement a feature you need. You can create your own opcodes. What a pity that so many RPG programmers still don’t know how to use subprocedures.