Archive for the ‘RPG Free Date Formatting’ Category
Problem: you need to add 15 days to a date stored in a manner where its parts are broken into 4 fields.
Here is the data structure used to capture the 4 fields at the time of the I/O (CC,YY,MM,DD). The DS defines fields over them for use by the calculations, specifically NAD_DATE, NAD_DATE_A and NAD_CCYYMMDD.
The Data Structure
NAD_DATE spanning positions 1 through 8, acts to contain the ccyymmdd components into a single field.
NAD_DATE_A is the character version of NAD_DATE.
NAD_CCYYMMDD is a work-field in *ISO format. NAD_DATE, in ccyymmdd format, is moved to this field.
Since the field NAD_DATE is an aggregate variant of the elementary fields in the data structure, the fields CC, YY, MM, DD contain the new sub-component values. If the field names are the same as those of the file, then an update operation will persist the values to the database.
This post is an extension of the post about how to obtain current date and time into a data structure (DS) which serves to format them in various ways. Some of the the DS values can be used in date-calculations while others are suitable for display on page headers and screens without further formatting.
The original post represents an older RPG-IV solution where everything is contained within the application program while this post focuses on a modern approach using RPG-ILE service programming. If you need to see an RPG-IV solution, you can see that post here.
Providing Current Date and Time using RPG-ILE programming techniques
Providing Current Date and Time using RPG-ILE programming techniques
The data structure that was presented in the post referenced above is augmented as shown here. It has been placed into a new source member the primary purpose of which is to copy the Data Structure into all application programs during compile-time using the ‘copy’ directive. The so-called ‘copy member’ also contains the definition of the prototype describing the signature used for the sub-procedure call invoked by the application program.
The copy member source containing the data structure and interface prototype is placed into a source file named QPROTSRC and given the name of DTETIMEDSH.
Shown below is the procedure. It has been placed into the source file QPROCSRC and given the name of DTETIMEDS.
Notable parts of the procedure are the “/copy” statement which pulls in the prototype definition and the data structure, the externally defined program status data structure (replace with your own), the procedure definition which establishes the name of the procedure as “getTimestamp”, its interface which defines the expected parameters to be passed to it by the client which calls “getTimestamp” and the mainline logic which then calls the internally defined subroutine called “getToday” which does all the work.
To use the procedure, the client program should include the following elements. First, there is the /copy statement used to pull in the source member for the prototype named DTETIMDSH.
In the startup routines, represented here by a subroutine called “startUp”, the client program calls the service program’s “getTimestamp” sub-procedure.
After the call completes, the DS field values will contain the current date in several different formats and in some cases, the component parts of month, day and year as shown below.
CURRENTDATE = 2010-11-17 CURRENTTIME = 09:53 AM DATENOW_ISO = 2010-11-17 DATENOW_USA = 11/17/2010 DATEUSADS TSMMDDYYYYA = 11172010 TSMMDDYYYY = 11172010. SYSDATEDS SYSDATE = 20101117. SYSTIME = 095313. TIMESTAMP = 2010-11-17-09.53.13.946000 TIMESTAMPISODS TSYYYYMMDDA = 20101117 TSYYYYMMDD = 20101117. TSTIMESTAMPA = 20101117095313 TSTIMESTAMPISO = 20101117095313. TSYEAR = 2010. TSCC = 20. TSYY = 10. TSYYMMDD = 101117. TSMONTH = 11. TSDAY = 17. TSHHMMSSA = 095313 TSHHMMSS = 095313. TSHHMM = 0953. TSHOUR = 09. TSMINUTE = 53. TSSECOND = 13.
The following date formatting functions reference the stand-alone fields defined below:
H option(*nodebugio) D @charA S 8 inz('04/12/01') D @charB S 10 inz('12/02/2004') D @charC S 8 inz('12/03/04') D @dateA S d inz(D'2004-12-04') D @numA S 6 0 inz(041205) D @numB S 7 0 inz(1041206) D @numC S 8 0 inz(20041207) D @numD S 6 0 inz(120804) D @numE S 8 0 inz(12092004)
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.