Date validation in DFSORT means making sure date values are valid (reasonable range and format) before you sort, filter, or convert them. DFSORT does not have a single "validate date" command. Instead, you validate by filtering: use INCLUDE or OMIT with conditions on the date field so that only records with dates in an acceptable range are processed, and invalid or out-of-range dates are excluded. When you use date conversion (e.g. TOGREG, TOJUL in INREC or OUTREC), invalid input (e.g. month 13, day 32, or Feb 30) can cause abends or wrong results depending on the product. This page explains how to validate dates using range filtering, how to handle invalid input, and how to combine conversion with validation.
In a programming language you might call a function like "isValidDate()" that returns true or false. In DFSORT, validation is done by selection: you keep only records that meet your criteria (e.g. date in range) and drop the rest with INCLUDE or OMIT. So "date validation" here means: defining what a valid date range is for your job, and using control statements so that only records with dates in that range (or only records that pass your tests) are written to SORTOUT or OUTFIL. Anything outside that range is "invalid" for your purpose and is excluded.
If your date is already stored as 8-byte character YYYYMMDD, you can keep only records where the date is between a low and high value. Character comparison of YYYYMMDD strings gives chronological order, so GE (greater-or-equal) and LE (less-or-equal) work correctly.
1INCLUDE COND=(41,8,CH,GE,C'20000101',AND,41,8,CH,LE,C'20301231')
This keeps only records where the 8-byte field at position 41 is between 2000-01-01 and 2030-12-31 inclusive. Records with dates before 2000 or after 2030 are omitted. Adjust the positions (41, 8) and the literals to match your layout and your chosen valid range. Using a range like 19000101–20991231 is common when you want to allow any "reasonable" calendar date and exclude garbage (e.g. 00000000, 99999999, or blanks).
Sometimes the input has blank dates, zero dates, or other sentinel values that should not be treated as real dates. You can omit them explicitly.
You can combine multiple OMIT statements (or one INCLUDE with AND conditions) so that only records with a non-blank, in-range date pass.
When DFSORT converts a date (e.g. with TOGREG or TOJUL in INREC/OUTREC), the source bytes must represent a valid date in the format you specify. Otherwise the result is undefined: the job might abend, or the product might produce a wrong or default value. Examples of invalid input:
| Example | Issue |
|---|---|
| Month 00 or 13 | Not a valid month |
| Day 00 or 32 | Not a valid day |
| Feb 29 in non-leap year | Feb has 28 days |
| Feb 30 in any year | Feb never has 30 days |
| Non-numeric bytes in date field | Conversion may abend or produce wrong value |
To reduce the chance of abends or bad output, either restrict input with INCLUDE/OMIT to a range you know is valid (e.g. after converting in INREC, filter on the converted field), or ensure upstream processes do not produce invalid dates. If your data has 2-digit years, also see Century windowing so that the correct century is applied.
If the source date is in a different format (e.g. MMDDYYYY, or Julian YYYYDDD), a robust approach is:
Example: source date at 50, 8 bytes, MMDDYYYY format. Convert to YYYYMMDD at output position 81, then keep only 2000–2030:
12INREC BUILD=(1:1,49,81:50,8,Y4W,TOGREG=Y4T,82:51,30) INCLUDE COND=(81,8,CH,GE,C'20000101',AND,81,8,CH,LE,C'20301231')
The BUILD builds the record with the converted date at 81–88. The INCLUDE then validates that the converted date is in range. Records with invalid source dates may already have caused problems in INREC (depending on the product); the INCLUDE further ensures that only records with a converted value in the desired range are passed to the sort and output.
YYYYMMDD has year, month, and day in that order. As a character string, "20230115" is less than "20231231", and "20221231" is less than "20230101". So character comparison (CH with GE, LE, GT, LT) gives the same result as chronological comparison. That is why validating with INCLUDE COND=(pos,8,CH,GE,...,AND,...,LE,...) is correct. Formats like MMDDYYYY or DDMMYYYY do not have that property, so if your date is in one of those, convert to YYYYMMDD first (e.g. in INREC) and then apply the range check on the converted field.
Imagine you have a box of cards with dates on them. Some cards might have silly dates like "Month 99" or "Day 32." Date validation is like having a rule: "Only keep cards where the date is between 2000 and 2030, and throw away the rest." DFSORT does not have a "is this date silly?" button. Instead, you say: "Keep only records where the date is at least 20000101 and at most 20301231." Everything else is thrown away. So we "validate" by only keeping the good ones.
1. What does "date validation" mean in DFSORT?
2. How can you keep only records whose date field is in a valid YYYYMMDD range?
3. What can happen when DFSORT converts an invalid date (e.g. month 13 or day 32)?
4. Why use INREC to build a YYYYMMDD field before validating?
5. How do you exclude records with blank or zero dates from processing?