We spend a great deal of time discussing dates (the kind you find on the calendar). From dealing with Y2K to using API programs to reformat dates, we have talked about many calendar-related issues here in MC.
This time, we elected to show how your RPG III and RPG IV programs can benefit from the versatility of the date data type. We felt the best way to show off the capabilities of the date data type was to create a date calculator that could perform many date-related functions but require very little code.
Picture This
The date calculator program utilizes date windowing and is therefore Y2K-friendly. Among other things, the program can be used to validate dates, change a date to a wide variety of output formats, calculate age, determine duration, or translate a date to a month or day of the week.
The DAT006RG date calculator program in Figure 1 can be called from any RPG III or RPG IV program. By passing the program a date (or two) and a parameter that we
refer to as an action code, you specify which function you would like the date calculator to perform. Because the program is so flexible and can serve so many different date-related functions, we have provided a list of the parameters and functions for the date calculator program. This list is in Figure 2.
Calculating duration and calculating age are two very common date functions in most business systems. Prior to the date data type, we had to use some reasonably complex routines to keep track of leap years, how many days were in a month, and which century the date belonged in. But RPG IV and the date data type changed all that. New RPG IV op codes that work with the date data type allow us to let the system keep track of all those things. Routines to convert a date to a day of the week, determine how old a date is, or calculate the duration between two dates have become very simple operations.
Since RPG III programs can call RPG IV programs, we thought everyone should be able to benefit from the date data type and the associated functions. It is for that reason that we put together this date calculator program.
As you can see from Figure 2, you can call the DAT006RG RPG IV program with either five or seven parameters, depending upon your needs. Parameters 1 and 2 are the input date and its format. The allowable input formats are mmddyy, ddmmyy, or yymmdd. Parameter 3 is the action code, which represents the date-related function you would like the program to perform. The action code will tell the date calculator program if you are interested in aging a date, calculating a duration, or reformatting a date for output.
Passing an action code of *FMTM, *FMTD, or *FMTY will cause the date calculator to reformat the input date to mmddyy, ddmmyy, or yymmdd, respectively, and return the new value to the calling program. An action code of *DOW will cause the representative day of the week to be returned to the calling program.
If you choose to use the *MONS, *DAYS, or *YEAR action codes, the action taken will depend upon whether you pass the program one or two dates. If you pass only one input date to the program, the date calculator will return the age of the input date in months, days, or years. On the other hand, if you pass the second input date and its format in parameters 6 and 7, the date calculator will determine the duration between both input dates and return that value to the calling program.
Parameter 4 of the DAT006RG program is used to return the requested value. If you have specified an invalid date edit picture (as described in the next paragraph) or action code, an error message will be returned to the calling program in parameter 5. The error message will describe the particular problem found.
A Picture Worth a Thousand Words
The *FMTA action code may be passed to the program to convert the input date to an alphanumeric representation like January 31, 2001. But the *FMTA action code may also be used to indicate that you would like to use a special date edit picture.
Dates can be written in dozens of ways. Since we did not want to reinvent the wheel, we chose to design our date calculator utility to optionally use the date input pictures that are accepted by IBM’s CEEDAYS API. To learn more about the CEE date APIs, see our article “In Search of a Good-looking Date” in the October 1996 issue of MC.
If you pass the optional date edit picture to the date calculator program along with your input date, the input date will be reformatted to match the date edit picture and returned in the output parameter. The DAT006RG program can accept a wide variety of date edit pictures, and Figure 3 shows a few of them. If you need to utilize others that are not included in Figure 3, refer to the ILE CEE APIs manual.
The Picture in the Window
Date windowing means that the program will take a six-digit input date and decipher whether the date belongs in the 20th or 21st century. If the two digits of the date that represent the year are 40 or above, the system will interpret that to mean that the date belongs in the 20th century (and the century digits are assumed to be 19). On the other hand, if the two digits representing the year are 39 or below, the 21st century will be assumed, and the century digits will be assumed to be 20. For example, if the input date is 12/31/99, the utilization of date windowing will mean that the date will be interpreted as 12/31/1999. An input date of 12/31/01 would be interpreted as 12/31/2001 (because the two digits representing the year are below 40).
You will have no problems with date windowing as long as the dates being used are between the years of 1940 and 2039. This should cover pretty much all dates except birth dates and special functions like long-range forecasting.
Seeing the Big Picture
The system you are working on may not use RPG IV, but that does not necessarily mean that you are shut out from using current tools and techniques.
As AS/400 programmers, all of us should allocate some time to studying and trying to keep current. Our time spent studying will be returned in the form of greater efficiency, improved programming technique, and more timely production.
The computer industry, particularly the development of the AS/400, is moving at light speed. You will not survive very long as an AS/400 programmer if you live like an ostrich, with your head buried in the sand.
Reference OS/400 Integrated Language Environment (ILE) CEE APIs (SC41-4861, CDROM QBKAMM01)
*===============================================================
* To compile:
*
* CRTBNDRPG PGM(XXX/DAT006RG) SRCFILE(XXX/QRPGLESRC) +
* DFTACTGRP(*NO) ACTGRP(QILE)
*
*===============================================================
* Program accepts an input date, input date format code, and
* action code. Data returned depends on action code. An optional
* second date (with format code) can be passed to compare with
* first date. If action code indicates duration and second date
* is not passed, program uses UDATE for second date.
* Action codes: *DOW - returns day of the week
* *FMTA - returns character date
* *FMTY - returns YYMMDD
* *FMTM - returns MMDDYY
* *FMTD - returns DDMMYY
* *MONS - returns # of months between date1 - date2
* *DAYS - returns # of days between date1 - date2
* *YEAR - returns # of years between date1 - date2
**********************************************************************
D AlphaDate s 35
d DateIn s 6 0
d Date10 s 10
d Date2In s 6 0
d DateOut s 6 0
d DoWhat s 5
d Duration s 5 0
d ErrorDsc s 35
d FmtIn s 1
d Fmt2In s 1
d FmtOut s 1
D InDate s 25
D InPicture s 35
d IsoDate s d
d IsoDate2 s d
D LilianDate s 9B 0
d OutData s 35
D OutPicture s 35
d Valid s 1
d Valid2 s 1
d Fc DS Inz
d Sev 4B 0
d Msgno 4B 0
d Flags 1
d Facid 3
d Isi 9B 0
* Returned ErrorDsc constants
d ActionCon C ‘Invalid - Action code’
d GreaterCon C ‘Invalid - 1st date > 2nd date’
d InvalidCon C ‘Invalid - 1st date’
d InvFmtCon C ‘Invalid - 1st date format code’
d InvFmt2Con C ‘Invalid - 2nd date format code’
d Inval2Con C ‘Invalid - 2nd date’
d ValidCon C ‘Valid - 1st date’
c *entry Plist
c Parm DateIn
c Parm FmtIn
c Parm DoWhat
c Parm OutData
c Parm ErrorDsc
c Parm Date2In
c Parm Fmt2In
c Exsr Validate
c If Valid = ‘Y’
c DoWhat Caseq ‘*VAL ‘ OutVal
c DoWhat Caseq ‘*DOW ‘ CalcDow
c DoWhat Caseq ‘*FMTA’ CalcFmt
c DoWhat Caseq ‘*FMTY’ CalcFmt
c DoWhat Caseq ‘*FMTM’ CalcFmt
c DoWhat Caseq ‘*FMTD’ CalcFmt
c DoWhat Caseq ‘*MONS’ CalcDiff
c DoWhat Caseq ‘*DAYS’ CalcDiff
c DoWhat Caseq ‘*YEAR’ CalcDiff
c Cas OutInval
c Endcs
c Endif
c Eval * inlr = *on
* Validate input dates
c Validate Begsr
c Eval Valid = ‘N’
c Select
c When FmtIn = ‘Y’
c *ymd Test(d) DateIn 01
c If *in01 = *off
c *ymd move DateIn IsoDate
c Eval Valid = ‘Y’
c Endif
c When FmtIn = ‘M’
c *mdy Test(d) DateIn 01
c If *in01 = *off
c *mdy move DateIn IsoDate
c Eval Valid = ‘Y’
c Endif
c When FmtIn = ‘D’
c *dmy Test(d) DateIn 01
c If *in01 = *off
c *dmy move DateIn IsoDate
c Eval Valid = ‘Y’
c Endif
c Other
c Eval ErrorDsc = InvFmtCon
c Endsl
c If Valid <> ‘Y’ AND
c ErrorDsc = *blanks
c Eval ErrorDsc = InvalidCon
c End
* If second date passed, validate it
c If %Parms >= 6
c Eval Valid2 = ‘N’
c Select
c When Fmt2In = ‘Y’
c *ymd Test(d) Date2In 01
c If *in01 = *off
c *ymd move Date2In IsoDate2
c Eval Valid2 = ‘Y’
c Endif
c When Fmt2In = ‘M’
c *mdy Test(d) Date2In 01
c If *in01 = *off
c *mdy move Date2In IsoDate2
c Eval Valid2 = ‘Y’
c Endif
c When Fmt2In = ‘D’
c *dmy Test(d) Date2In 01
c If *in01 = *off
c *dmy move Date2In IsoDate2
c Eval Valid2 = ‘Y’
c Endif
c Other
c Eval ErrorDsc = InvFmt2Con
c Eval Valid = ‘N’
c Endsl
c If Valid2 <> ‘Y’ AND
c ErrorDsc = *blanks
c Eval ErrorDsc = Inval2Con
c Else
c If IsoDate > IsoDate2
c eval Valid = ‘N’
c eval ErrorDsc = GreaterCon
c Endif
c Endif
c Endif
c Endsr
* Validate date was the action code, output valid constant
c OutVal Begsr
c eval ErrorDsc = ValidCon
c Endsr
* Output invalid action code
c OutInVal Begsr
c eval ErrorDsc = ActionCon
c Endsr
* Calculate interval between dates
c CalcDiff Begsr
c if %Parms <= 5
c *mdy move Udate IsoDate2
c endif
c Select
c When DoWhat = ‘*MONS’
c IsoDate2 SubDur IsoDate Duration:*M
c When DoWhat = ‘*YEAR’
c IsoDate2 SubDur IsoDate Duration:*Y
c
c When DoWhat = ‘*DAYS’
c IsoDate2 SubDur IsoDate Duration:*D
c Endsl
c Movel Duration OutData
c Endsr
* Convert input date to requested format indicated in Action Code
c CalcFmt Begsr
c Select
c When DoWhat = ‘*FMTY’
c *ymd Move IsoDate DateOut
c Movel DateOut OutData
c When DoWhat = ‘*FMTM’
c *mdy Move IsoDate DateOut
c Movel DateOut OutData
c
c When DoWhat = ‘*FMTD’
c *dmy Move IsoDate DateOut
c Movel DateOut OutData
c
c When DoWhat = ‘*FMTA’
* If character date requested and no picture representing the format
* of the output was passed in, set the default picture
c If OutData = *blanks
c eval OutPicture = ‘Mmmmmmmmmz ZD, YYYY’
c else
c movel OutData OutPicture
c endif
c Exsr Alpha
c eval OutData = AlphaDate
c Endsl
c Endsr
* Retrieve day of the week
c CalcDow Begsr
c eval OutPicture = ‘Wwwwwwwww’
c exsr Alpha
c eval OutData = AlphaDate
c Endsr
* Retrieve character description of the date (can actually be used
* to convert date from one format to another - with or without
* separator characters - using the input picture from outdata).
c Alpha Begsr
c move IsoDate Date10
c movel Date10 InDate
c movel ‘YYYY-MM-DD’ InPicture
* Convert input date to lilian date format
c CALLB(D) ‘CEEDAYS’
c PARM InDate
c PARM InPicture
c PARM LilianDate
* Convert lilian date to character date
c CALLB(D) ‘CEEDATE’
c PARM LilianDate
c PARM OutPicture
c PARM AlphaDate
c PARM Fc
c Endsr
Figure 1: RPG IV date calculator program
Parameter Value Description
1. Input date Date as mmddyy, This is the primary input date for the date calculator, yymmdd, or ddmmyy as described by parameter 2.
2. Date format M for mmddyy, D for This format option is used to describe the format of
ddmmyy, or Y for the input date. yymmdd
3. Action code *VAL *VAL will validate the input date or dates. See parameter 5 (Error message) for potential errors.
*MONS *MONS returns either how many months old the input date is or how many months have elapsed between the first and the second input date.
*DAYS This is the same as *MONS, except the result is in days instead of months.
*YEAR This is the same as *MONS, except the result is in years instead of months.
*FMTM If *FMTM is specified, the input date will be returned in a mmddyy format.
*FMTD *FMTD is essentially the same as *FMTM, except that the date is returned in a ddmmyy format.
*FMTY *FMTY is essentially the same as *FMTM, except that the date is returned in a yymmdd format.
*DOW The weekday that represents the input date will be returned to the calling program. The weekday will be spelled out as Monday, Tuesday, and so on.
*FMTA The input date will be returned in complete alphanumeric form. For example, an input date of 013101 would be returned as January 31, 2001, unless a valid edit picture is specified in parameter 4. If a valid edit picture (see Figure 3) is specified, the date will be returned in the specified format.
4. Output Output based upon The combination of the input date and the action code action requested will determine what output is returned to this field (to the calling program).
Optional edit picture The API edit picture can be inserted here to return any (see Figure 3) when an valid date format. For some examples, check out the *FMTA action code is entries in Figure 3. This entry is valid only if you have specified chosen the *FMTA action code.
5. Error message Errors found in the input If invalid dates or action codes are specified when the program is called, a description of the error will be returned. Possible errors include the following: Invalid - Action code
Invalid - 1st date > 2nd date
Invalid - 1st date
Invalid - 1st date format code Invalid - 2nd date format code
Invalid - 2nd date
Valid - 1st date
6. Second input Date as mmddyy, This is the secondary input date for the date date (optional) yymmdd, or ddmmyy calculator, as described by parameter 7.
7. Second date Y for yymmdd, M for This format option is used to describe the format of format (optional) mmddyy, or D for the secondary input date.
ddmmyy
Date Picture Sample Description
WWW TUE This is the three-character day of the week in uppercase. The weekday could be printed in mixed case if the second and third characters of the picture were lowercase.
WWWWWWWWWW TUESDAY This is the ten-character day of the week in uppercase. Mixed case may be used by applying the same rules as above.
Wwwwwwwwwz Tuesday This is the same ten-character day of the week as above, except the case is mixed and trailing blanks are suppressed because the picture ends with the character z.
MMM DEC This is the three-character abbreviation for the month. The abbreviation could be printed in mixed case if the second and third characters of the picture were lowercase.
MMMMMMMMMM DECEMBER This is the ten-character name of the month in uppercase. Mixed case may be used by applying the same rules as above.
Mmmmmmmmmz December This is the same ten-character name of the month as above, except the case is mixed and trailing blanks
Figure 2: Parameters for the date calculator program
are suppressed because the picture ends with the character z.
DD MMM YY 01 DEC 98 This is the day-month-year format. The day and year are entered as two-digit numeric (including leading zeros). The month is entered as the three-character abbreviation.
DD Mmmmmmmmmm YY 01 December 98 This is also the day-month-year format. The day and year are entered as two-digit numeric (including leading zeros). The month is entered as the full ten- character description (including blanks).
ZD Mmmmmmmmmz YY 1 December 98 This is the same as above, except leading zeros and trailing blanks are suppressed.
Mmmmmmmmmz ZD, December 1, 1998 This is the same as above, except the input date is YYYY specified as month-day-year. A comma separates the day and year. The year is specified as four digits (including the century).
Wwwwwwwwwz, Tuesday, Dec 1, 1998 This is the same as above, but the day of week has Mmm ZD, YYYY been added and the month is abbreviated.
YYMMDD 981201 This must include all six digits of the date (including leading zeros).
YYYYMMDD 19981201 This is the same as above, except the entire year, including the century, is specified.
YYYY-MM-DD 1998-12-1 This eight-digit date is specified with dashes as a separator character. Leading zeros are not mandatory for the month and day.
MMDDYY 120198 This month-day-year six-digit date format requires leading zeros on the month and day.
MM/DD/YY 12/01/98 This is the same as above, except slashes are included as separator characters. Leading zeros on the month and day must be specified.
ZM/ZD/YY 12/1/98 This is the same as above, except leading zeros on the month and day may be suppressed.
MM/DD/YYYY 12/01/1998 This eight-digit date is specified with slashes as separator characters. Leading zeros are required on the month and day.
DD.MM.YY 01.12.98 This is a six-digit day-month-year format with decimals as separator characters. Leading zeros are required on the month and day.
YY.DDD 98.335 This is a Julian date with a decimal as a separator character.
YYDDD 98335 This is the same as above, but with no separator characters.
Figure 3: Sampling of the edit pictures that the DAT006RG program can accept
LATEST COMMENTS
MC Press Online