Blog Archive

RPGLE date manipulation - Date difference, Add or substract days, months or years

Found this really nice article by by Joel Cochran in ITJungle.
Click here for more RPGLE Date Articles

DATE MATH

With real date fields, and some additional supplied BIFs, date math couldn't be any easier. There are BIFs for adding and subtracting days, months, or years: appropriately, these are %days, %months, and %years. Below are some examples of how to use these BIFs with your date variable:
 d myDate          s               d   inz(d'2004-05-01')

 /free
   // myDate = '2004-05-01'
    myDate = myDate + %days(3) ;
   // myDate = '2004-05-04'

    myDate = myDate + %months(1) ;
   // myDate = '2004-06-04'

    myDate = myDate - %years(2) ;
   // myDate = '2002-06-04'

    *inlr = *on ;
 /end-free

CALCULATING DATE DIFFERENCES

Calculating the difference between two dates is also very easy, using another BIF, %diff. This BIF allows you to compare two dates and to calculate the difference in days, months, or years.
d myDate1         s               d   inz(d'2004-05-01')
d myDate2         s               d   inz(d'2004-05-08')
d diff_days       s              2s 0
d diff_months     s              2s 0
d diff_years      s              4s 0

 /free
    diff_days = %diff( myDate2 : myDate1 : *days );
    // diff_days = 7

    diff_months = %diff( myDate2 : myDate1 : *months ); 
    // diff_months = 0

    diff_years = %diff( myDate2 : myDate1 : *years );
    // diff_years = 0

    *inlr = *on ;
 /end-free

You can get a negative return value if the first parameter is an earlier date than the second parameter. To avoid this, either make sure that the higher date is always first or use the %abs (absolute value) BIF on the return value:
diff_years = %diff( myDate2 : myDate1 : *years );
diff_years = %abs(diff_years);
dsply diffyears;

You may want to embed this result in a character string. Typically, %char will do this for you nicely:
 /free
     myString = 'There is a difference of ' +
                        %char( %diff( myDate2 : myDate1 : *days ) ) +
                        ' days!' ;
      // myString = 'There is a difference of 7 days!'
 /end-free

By default this will suppress leading zeros. However, if you need leading zeros you may want to use %editc instead of %char, but you will quickly discover something interesting:
 /free
     myString = 'There is a difference of ' +
                        %editc( %diff( myDate2 : myDate1 : *days ) : 'X' ) +
                        ' days!' ;
      // myString = 'There is a difference of 0000000007 days!'
 /end-free

The return field for %diff is really 10 numeric! This means that if you want to use leading zeros, and still expect the correct number of characters, you will need to first move the value into an appropriately sized numeric field and then perform %editc. At first this seems strange, perhaps even silly, but once you realize that this BIF, and most others in this article, also apply to %time and %timestamp values, it is easy to conceive of needing 10 digits returned.

RETRIEVE DATE PORTIONS

The %subdt BIF allows you to extract a portion of a date field, such as the day, month, or year.
d myDate          s               d   inz(d'2004-05-01')
d days            s              2s 0
d months          s              2s 0
d years           s              4s 0
d myString        s            128a

 /free
    days = %subdt( myDate : *days );
    // days = 1

    months = %subdt( myDate : *months );
    // months = 5

    years = %subdt( myDate : *years );
    // years = 2004 

    *inlr = *on ;
 /end-free

You can also use short cuts for the second parameter: *d instead of *days, *m instead *months, and *y instead of *years.

As I discussed with %diff above, using these results in character strings is no problem with %char, but if you use %editc you should be aware that %subdt is going to return a 10-digit numeric.
Read complete article here ...


4 comments :