MainframeMaster

Date Validation

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.

Date & Time Processing
Progress0 of 0 lessons

What "Date Validation" Means in DFSORT

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.

Valid Date Ranges with INCLUDE

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.

text
1
INCLUDE 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).

Excluding Invalid or Sentinel Values with OMIT

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.

  • Blank 8-byte character date: OMIT COND=(41,8,CH,EQ,C' ') — eight spaces. That drops any record where the date field is all blanks.
  • Zero or low sentinel: If the date is stored as packed or zoned decimal, use the appropriate format: e.g. OMIT COND=(41,4,PD,EQ,0) to drop zero. For character YYYYMMDD, OMIT COND=(41,8,CH,EQ,C'00000000') drops that value.

You can combine multiple OMIT statements (or one INCLUDE with AND conditions) so that only records with a non-blank, in-range date pass.

Invalid Dates That Conversion May Reject or Mis-handle

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:

Examples of invalid date input
ExampleIssue
Month 00 or 13Not a valid month
Day 00 or 32Not a valid day
Feb 29 in non-leap yearFeb has 28 days
Feb 30 in any yearFeb never has 30 days
Non-numeric bytes in date fieldConversion 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.

Validate After Converting in INREC

If the source date is in a different format (e.g. MMDDYYYY, or Julian YYYYDDD), a robust approach is:

  1. Use INREC to convert the date to YYYYMMDD at a fixed position.
  2. Use INCLUDE (or OMIT) on that converted field to keep only dates in your valid range.

Example: source date at 50, 8 bytes, MMDDYYYY format. Convert to YYYYMMDD at output position 81, then keep only 2000–2030:

text
1
2
INREC 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.

Why YYYYMMDD for Range Checks?

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.

Explain It Like I'm Five

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.

Exercises

  1. Write an INCLUDE that keeps only records where an 8-byte YYYYMMDD at position 1 is between 19900101 and 20251231.
  2. Write an OMIT that drops any record where the 8-byte date at position 40 is blank (eight spaces).
  3. Why is it safer to convert to YYYYMMDD in INREC and then filter on that field when the source is MMDDYYYY?

Quiz

Test Your Knowledge

1. What does "date validation" mean in DFSORT?

  • Only converting dates
  • Ensuring dates are valid (reasonable range, format) and filtering or handling invalid dates—using INCLUDE/OMIT for ranges, or accepting that conversion can fail on bad input
  • Sorting by date only
  • Century windowing only

2. How can you keep only records whose date field is in a valid YYYYMMDD range?

  • Use SUM
  • Use INCLUDE COND=(start,8,CH,GE,C'19000101',AND,start,8,CH,LE,C'20991231') (or your chosen range) so only dates in that range pass
  • Use MERGE only
  • OUTREC only

3. What can happen when DFSORT converts an invalid date (e.g. month 13 or day 32)?

  • Nothing
  • Behavior is product-dependent: the job may abend, produce a wrong value, or fill with zeros/blanks. So validating the range before conversion or filtering after conversion is important
  • Always abend
  • Always fill with zeros

4. Why use INREC to build a YYYYMMDD field before validating?

  • INREC cannot build dates
  • If the source date is in another format (e.g. MMDDYYYY or Julian), convert it in INREC to YYYYMMDD at a fixed position, then use INCLUDE/OMIT on that field for a clear range check
  • Only for reports
  • To avoid INCLUDE

5. How do you exclude records with blank or zero dates from processing?

  • Cannot be done
  • Use OMIT COND=(start,8,CH,EQ,C' ') for blanks or the appropriate test for zeros (e.g. PD/ZD format). Or INCLUDE with GT low date so zeros/blanks fall below the range
  • Only with JOINKEYS
  • SUM removes them