I received an email asking me the following question:
What about date validation?
Dates on a screen are usually displayed as MMDDYY. I don't need to add days or months to it, I need to ensure that the date itself is valid.
I can think of two approaches of displaying and validating dates on a display file.
- Use a date field.
- Use a 6,0 numberic field.
Below is a simple display file I have created for this post:
01 A DSPSIZ(24 80 *DS3) 02 A INDARA 03 A R SCREEN 04 A 6 3'Date 1 .' 05 A ZDATE1 L B 6 13DATFMT(*MDY) 06 A 7 3'Date 2 .' 07 A ZDATE2 6 0B 7 13EDTCDE(Y) 08 A EDTMSK(' & & ') 09 A 50 ERRMSG('Date 2 is not + 10 A valid')
The INDARA on line 2 means that I will be using a Indicator Data Structure in my RPGLE/RPG IV program rather than number indicators. To learn more about the Indicator Data Structure read the post No More Number Indicators.
On line 5 I have defined the field ZDATE1 as a date data type field, L in Date Type field of the DDS. I do not give the length of a date data type field, just the type. The format of the date is defined with the DATFMT in the Functions field of the DDS.
On line 6 I have defined the field ZDATE2 as a numeric field six long with no decimals (6,0). I am using EDTCDE(Y) to format the number with slashes (/) in it.
On line 7 I am using the EDTMSK to control how ZDATE2 is entered. The EDTMSK(' & & ') means that after entering the first two characters, month, the cursor automatically moves to the fourth position to allow entry of the next two characters, day, and then the cursor moves automatically to the seventh position to allow the entry of the year.
On line 8 is the error that will be displayed when the equivalent of indicator 50 is turned "on" in the RPGLE/RPG IV program.
I am not going to describe the code to do with the Indicator Data Structure in the RPGLE/RPG IV program below, as you should have learn about that from the No More Number Indicators post.
01 FTESTDSPF CF E WORKSTN indds(IndDs) 02 D IndDs DS qualified 03 D ErrDate2 50 50N /free 04 ZDATE1 = %date() ; 05 dow (1 = 1) ; 06 exfmt SCREEN ; 07 test(de) *mdy ZDATE2 ; 08 if (%error) ; 09 IndDs.ErrDate2 = *on ; 10 else ; 11 IndDs.ErrDate2 = *off ; 12 leave ; 13 endif ; 14 enddo ; 15 *inlr = *on ;
On line 4 I have had to move a date into the ZDATE1 field. If I did not I would get the 'The year postion of a Date or Timestamp value is not in the correct range' error, RNQ0114, when the display file's record format SCREEN was displayed, on line 6.
When the record format SCREEN is displayed it looks like:
Date 1 . 09/20/13 Date 2 . 0/00/00
If an invalid date is entered into the first field, ZDATE1, as the error is handled by the display file the following error message is displayed: 'Field value is not an allowed date. Reason code 9.'.
If a number, which is not a valid date, is entered into the second field, ZDATE2, then the RPGLE/RPG IV program performs the validation on line 7 using the TEST(DE) operation code. The TEST operation code is used to validate dates, times, and timestamps. The D in the parentheses (or brackets if you are not using American English) denotes that I am testing for a date, and E is the error flag to turn on the %error indicator. The next part is the date format, in our case *MDY, and finally the field I am validating, ZDATE2. If the number is not a valid *MDY date then the %error indicator is turned on.
On line 8 I test for the %error indicator, if it is on I execute line 9, whuich turns on the indicator IndDs.ErrDate2, which is the equivalent of indicator 50 in the display file, see line 3. Indicator 50 conditions the display of the error message in the display file: 'Date 2 is not valid'.
If there is no error then Inds.ErrDate2 is turned off, and I exit the DO-loop to continue processing.
Which of these two methods is my preference?
I prefer and use the second method, using a numeric field on the display file which I then validate as a date. I do this as I can display a meaningful error to the user if the date is invalid. in my opinion a message like 'From date is invalid' is easier for a user to understand what is wrong, rather than 'Field value is not an allowed date. Reason code 9.'.
Do you know of a method that you think is better? If so please add a Comment below describing how you would do it.
You can learn more about these from IBM's website:
This article was written for IBM i 7.1, and it should work with earlier releases too.