On RPG-LE Development

Postings on RPG-LE and i5/OS

Posts Tagged ‘RPGLE Date Testing

Formatting Current Date and Time using a Data Structure and RPG-IV

leave a comment »

It’s rare to write a program and not need some form of date and time. Often you need both. With a carefully crafted Data Structure, extracting the date and time becomes relatively painless. The bonus with this approach is that you get today’s date and time formatted in various ways. This proves useful for comparison operations, aging scenarios, and report page and screen headers.


Using An RPG-IV Approach

This approach uses RPG-IV based code and a basic data structure.

Shown below is a data structure defining a date/time format. Under TimeStamp the data has been subdivided where values for the whole timestamp can be obtained (tsTimeStamp) in addition to acquiring the following values.

Hours, minutes and second in field tsHHMMSS
Century, year, month and day in field tsYYYYMMDD [*ISO format]
Month, day, century and year in field tsMMDDYYYY [*USA format]

     D TimeStamp       DS
     D   tsTimeStamp                 14S 0
     D   tsHHMMSS                     6S 0 OVERLAY(tsTimeStamp:1)
     D     tsHour                     2S 0 OVERLAY(tsHHMMSS)
     D     tsMinute                   2S 0 OVERLAY(tsHHMMSS:*NEXT)
     D     tsSecond                   2S 0 OVERLAY(tsHHMMSS:*NEXT)
     D   tsYYYYMMDD                   8S 0 OVERLAY(tsTimeStamp:7)
     D     tsYear                     4S 0 OVERLAY(tsYYYYMMDD)
     D     tsMonth                    2S 0 OVERLAY(tsYYYYMMDD:*NEXT)
     D     tsDay                      2S 0 OVERLAY(tsYYYYMMDD:*NEXT)
     D   tsMMDDYYYY                   8S 0 OVERLAY(tsTimeStamp:7)
     D     tsMM                       2S 0 OVERLAY(tsMMDDYYYY)
     D     tsDD                       2S 0 OVERLAY(tsMMDDYYYY:*NEXT)
     D     tsYYYY                     4S 0 OVERLAY(tsMMDDYYYY:*NEXT)

     D DateNow_ISO     S               D   DATFMT(*ISO)
     D DateNow_USA     S               D   DATFMT(*USA)
     D BirthDate       S               D   DATFMT(*ISO)

Also shown are some stand-alone fields to contain the current date and time in *ISO and *USA format in addition to a date defining an arbitrary birthdate.

To populate the data structure with the current date and time, the following code is used.

C                   TIME                    tsTimeStamp

Although the data structure contains a properly formatted date and time, the problem is that we don’t know which format was used by the system to populate the data structure. System date formats can be established by third-party software packages or by setting the appropriate i5/OS system values. The next set of code shown below makes that determination. The code is biased to *ISO format.

      * What format is the timestamp in?  We want YYYYMMDD
     C     *ISO          TEST(D)                 tsYYYYMMDD             99
     C     *IN99         IFEQ      *OFF
     C                   MOVE      tsYYYYMMDD    DATENOW_ISO
      *
      * Date is not in *ISO format; check for *USA
     C                   ELSE
     C     *USA          TEST(D)                 tsMMDDYYYY             99
     C     *IN99         IFEQ      *OFF
     C                   MOVE      tsYYYYMMDD    DATENOW_USA
     C                   MOVE      DATENOW_USA   DATENOW_ISO
     C                   ENDIF
      *
     C                   ENDIF

With the system date obtained in an *ISO format, calculations like the one below which determine the number of years elapsed from a given date can be safely made without the system issuing an error.

     C                   MOVE      RDDOB         BIRTHDATE
     C     DATENOW_ISO   SUBDUR    BIRTHDATE     S2AGE:*Y


Redesigning the Solution Using an RPG-ILE Service Program


To see how this design is converted to use a more modern approach which uses a RPG-ILE service program, click here.

Written by Ben

2010/02/03 at 12:32 am

RPGLE and DDS MAPVAL

leave a comment »

I have an input date field on a display that I wanted to initially show as blank because it is used as a filter-by-date value.  Blank means nothing was entered by the user so don’t do the filtering.  I wanted DDS to force a valid *USA format for input.    I also wanted blanks to be a valid input value so the user could clear a previously entered filter-date.

DDS provides a very easy approach to solving this problem without a lot of code in the application. The key to this is the DDS MAPVAL function.

|...+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8
00030A            S1FDATE         L         DATFMT(*MDY) DATSEP('/')
00040A                                      MAPVAL(('01/01/40' *BLANK))

During an output operation, the field data is compared to each program-value on the MAPVAL keyword in the order in which the program-values are specified. For the first match that is found, the corresponding system-value replaces the current field data. If a match does not exist, the field data does not change.

During an input operation, the field data is compared to each system-value on the MAPVAL keyword in the order in which the system-values are specified. For the first match that is found, the corresponding program-value replaces the current field data. If a match does not exist, the field data remains the same.

Option indicators are not valid for this keyword, although you can use option indicators to condition the field for which it is specified.
On output, if the field data equals ’01/01/40′, the field data is changed to all blanks. On input, if the field data is blank, the field data is changed to ’01/01/40′.

Inside the RPGLE application I defined a few dates to perform format conversion.

D SAVFDATE        S               D   DATFMT(*USA)
D DFTFDATE        S               D   DATFMT(*USA) INZ(D'0001-01-01')
D CCYYMMDD        S               D   DATFMT(*ISO)

Finally, the logic created to pull it all together.

 * A valid *USA date will be returned if entered.  A freshly initialized         
 * screen will show the date field as blank, but when it gets to this code       
 * the field has been initialized by RPG to '01/01/0001' which is contained      
 * in DFTFDATE.  Comparing SAVFDATE to DFTFDATE is in essence testing for        
 * the fact the user has not entered a valid search date.                        
C     SAVFDATE      IFNE      DFTFDATE                                           
C                   MOVE      SAVFDATE      CCYYMMDD                             
C                   MOVE      CCYYMMDD      SAVFDATEN                            
C     RHCTDT        IFEQ      SAVFDATEN                                          
C                   MOVEL     @YES          INCLUDE                              
C                   ELSE                                                         
C                   MOVEL     @NO           INCLUDE                              
C                   ENDIF                                                        
C                   ENDIF       

Written by Ben

2010/01/30 at 1:10 am

Follow

Get every new post delivered to your Inbox.