Published on System iNetwork (http://systeminetwork.com)
Date Math... Did You Know?
By cbushong
Created Apr 17 2008 - 19:22

Date Math Made Easy

Here is a diabolically simply way to perform date arithmetic.

We've all seen the original ADDDUR (add date duration) and SUBDUR (subtract date duration or subtract two dates given a duration) opcodes. In i5/OS V5R1 (which is what IBM 'i' was called back then), IBM added a built-in function that simplifies SUBDUR and allows you to "just do it" when it comes to ADDDUR.

Date Addition

Let's start with the ADDDUR opcode first, since it's the easiest to migrate to free format and to traditional syntax using the EVAL opcode.

The ADDDUR opcode is deprecated by the plus sign. Yep, that's it; instead of this:

     C     INVDATE       ADDDUR    30:*DAYS      DUEDATE

you can now do this:

      /free                 
          duedate = invdate + %days(30);
      /end-free                 

or this:

     C                   eval      duedate = invdate + %days(30)

Even cooler, would be to do this:

     C                   eval      duedate += %days(3)

This adds three days to the DUEDATE, date variable, a shorthand version of the similar (albeit different) and more verbose example previously listed.

But this also gives you something you didn't really have in traditional syntax. Imagine this:

     C                   if        (today < duedate + %days(30))
              // overdue!
     C                   endif

This compares the date variable TODAY to the DUEDATE plus 30 days. This is very cool.

RPG TnT: 101 Dynamic Tips 'n Techniques with RPG IV by Bob Cozzi is available now.
[1] The latest book from author Bob Cozzi is available now. This 300-page book contains 101 example 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. [2]

Data Subtraction

The SUBDUR is completely deprecated with two different techniques. The first is the minus operator. As with the plus operator, a simple match may be accomplished using the minus with a duration of days, months, or years (hours, minutes, and seconds for time variables).

So now the following:

     C     dueDATE       SUBDUR    30:*DAYS      invDATE

can be replaced with the following:

      /free                 
          invdate = duedate - %days(30);
      /end-free                 

or this:

     C                   eval      invDate = dueDate - %days(30)

Even cooler, you can do this:

     C                   eval      dueDate -= %days(3)

The key to all of this is the built-in function %DAYS, %MONTHS, or %YEARS. These built-in functions cast a numeric variable or literal into a duration that can be used by date/time arithmetic. But there's more to date subtraction.

Subtracting Two Date Values

The way IBM decided to implement subtraction of two dates is with a built-in function. The built-in function %DIFF performs the subtraction and returns a duration based on one of the parameters of %DIFF. The syntax for %DIFF follows:

    result = %DIFF( date1  :  date2  :  duration )

To use %DIFF, place the most current date on the first parameter and the oldest date on the second parameter. The third parameter is required and must contain *DAYS, *MONTHS, or *YEARS and indicates the value you want %DIFF to return as a result of the date subtraction.

NOTE: If performing %DIFF using Time data types, then the third parameter must be *MSECONDS, *SECONDS, *MINUTES, or *HOURS.

To use %DIFF in traditional syntax, the EVAL opcode must be used, as follows:

     C                   eval      days = %diff(duedate:invdate:*DAYS)

In this example, the INVDATE is subtracted from the DUEDATE giving the number of days between those two dates. If INVDATE is older than DUEDATE, a positive number is returned; otherwise, a negative number is returned.

It can also be used in conditional statements, for example:

     C                   if        %diff(today:duedate:*DAYS) > 30
     C**   Invoice payment is more than 30 days overdue
     C                   endif

In free format, the syntax is similar, for example:

      /free 
          days = %diff(duedate:invdate:*DAYS);
          if %diff(today:dueDate:*Days) > 30;
             // We are more than 30 day overdue!
          endif; 
      /end-free 

One thing that doesn't work is returning the number of years, months, and days between two dates. That is, you can't calculate 3 years, 7 months, and 10 days between two dates -- only the full value of 3 years or 43 months or whatever that number of days would be.

To return a fractionalized value, you have to use something like the DateDiff() function in RPG xTools (www.RPGxTools.com [3]) or write the routine yourself.

Dates are not incredibly fun to use in RPG IV. But there's one more thing. Do you have any "date" fields defined as eight-digit numeric? You can still use them with %DIFF or the plus and minus signs in date math.

Just wrap the numeric value in %DATE and use it the way you would any other date variable. For example:

     D INVDTE          S              8S 0 INZ(20080228)

      /free
          invdte = %dec(%date(invdte:*ISO)+%days(30))
      /end-free

In this example, the numeric field INVDTE is converted to a true Date data type, 30 days is added to that date value, and then its converted back into a numeric value using %DEC. Everything in this example works on i5/OS V5R2 except the %DEC portion. Sadly, that requires V5R3 or later.

Bob Cozzi, a black belt in Judo, started practicing Judo in 1974 and began to learn programming in 1975. Today, Bob runs RPG World [4], the most popular third-party, commercial RPG IV Training Event in the world. The next RPG World Conference [5] is open to all, and is coming up in May 2008.

Copyright © Penton Media

Source URL: http://systeminetwork.com/article/date-math-did-you-know

Links:
[1] http://www.amazon.com/dp/1583041214?tag=rw0c-20&camp=14573&creative=327641&linkCode=as1&creativeASIN=1583041214&adid=0FDDKRAMASMW6SZB3462&
[2] http://www.amazon.com/dp/1583041214?tag=rw0c-20&camp=14573&creative=327641&linkCode=as1&creativeASIN=1583041214&adid=0FDDKRAMASMW6SZB3462&
[3] http://www.RPGxTools.com
[4] http://www.rpgworld.com
[5] http://www.rpgworld.com