In a recent Tuesday Tips segment, I illustrated a simplified technique to calculate the duration between two date values. This technique returned the number of years, months, and days between the two dates. For example, if you wanted to know how long it's been since the first moon landing on July 20, 1969, you would subtract that date from today's date and get 14,179 days. But it you could calculate this duration as 38 years, 9 months, and 26 days, it would be more human-friendly. So that's what the original Tuesday Tips video proposed, using a simple routine to calculate the years, months, and days between two dates. But then I got a message from one of the RPG compiler writers at IBM Canada who unofficially suggested an alternative routine.
First, the problem with the original routine I presented is that it could be off by one day from time to time. The modified technique, while not as straightforward or concise, produces accurate results in all the situations we tested.
The revised technique requires that you calculate the duration three times -- once for the number of years, then months ,then days, but it uses a "trick" in between each calculation that subtracts the previous results, yielding the correct months and days durations. The pseudo code might look like this:
years = newDate - oldDate newDate = newDate - years months = newDate - oldDate newDate = newDate - months days = newDate - oldDate
To make this work, the %DIFF built-in function or the SUBDUR opcode must be used, as follows:
rtnDur.Years = %Diff(newDate:oldDate:*YEARS);
newDate -= %Years(rtnDur.Years);
rtnDur.Months = %Diff(newDate:oldDate:*Months);
newDate -= %Months(rtnDur.Months);
rtnDur.Days = %Diff(newDate:oldDate:*Days);
| RPG TnT: 101 Dynamic Tips 'n Techniques with RPG IV by Bob Cozzi is available now. | |
![]() |
The latest book from author Bob Cozzi is 300 pages, containing 101 examples of RPG IV Tips and Techniques for everyday programming tasks, from date calculations, to regular express searches, to using APIs. Cozzi wrote down every cool technique he's found over the years, updated them, and consolidated them into this compact book that is a great desktop companion, and it includes full example source code. Order your copy today. |
In addition, the NEWDATE variable must be the later of the two dates, so the following controls could be necessary just before the %DIFF operations:
if (date1 > date2); // Which date is older?
newDate = date1;
oldDate = date2;
else;
newDate = date2;
oldDate = date1;
endif;
To tie this up, I've put together a little subprocedure called DATEDUR that accepts two date values as its parameters, and returns a data structure containing three integers, years, months, and days. This return structure would be defined as follows:
D DateDur_T DS Qualified Inz
D years 10I 0
D months 10I 0
D days 10I 0
To calculate the years, months, and days between two dates, call DATEDUR as follows:
D dur DS LikeDS(dateDur_T) Inz
D today S D Inz(*SYS)
D landing S D Inz(D'1969-07-20')
/free
dur = datedur(today:landing);
/end-free
I've reproduced the modified DATEDUR subprocedure, in its entirety, here for you. You can also download it and the prototype source member named DATES in the QCPYSRC source file by visiting www.RPGWord.com and clicking on the Downloads link.
H NOMAIN
H OPTION(*SRCSTMT:*NODEBUGIO)
/COPY RPGCODER/QCPYSRC,dates
P DateDur B Export
D DateDur PI LikeDS(DateDur_T)
D date1 D Const DATFMT(*ISO)
D date2 D Const DATFMT(*ISO)
D olderDate S D Datfmt(*ISO)
D newerDate S D Datfmt(*ISO)
D rtnDur DS LikeDS(DateDur_T) Inz
/free
monitor;
if (date1 > date2); // Which date is older?
newerDate = date1;
olderDate = date2;
else;
newerDate = date2;
olderDate = date1;
endif;
rtnDur.Years = %Diff(newerDate:olderDate:*YEARS);
newerDate -= %Years(rtnDur.Years);
rtnDur.Months = %Diff(newerDate:olderDate:*Months);
newerDate -= %Months(rtnDur.Months);
rtnDur.Days = %Diff(newerDate:olderDate:*Days);
on-error *ALL;
clear rtnDur;
endmon;
return rtnDur;
/end-free
P DateDur E
Bob Cozzi recently produced the RPG World, his annual conference for RPG IV programmers and managers. This summer, Bob is holding RPG World Academy, a series of one-day seminars for RPG IV programmers; the first in this series is Subprocedures and Service Programs, and the second is RPG IV for the Web. RPG World Academy is being held in cities throughout North America during the summer of 2008. Visit www.RPGWorld.com and click the Academy link for more details, dates, and locations.