There are multiple Date Functions by which you can reformat input dates. Modern mainframe jobs frequently need to stamp files with run-date timestamps, convert between Julian and Gregorian calendars, subtract business days, and generate aging metrics. DFSORT’s powerful DATE functions—available through INREC, OUTREC, OUTFIL, and ICETOOL—let you accomplish all of this with a few control-card lines, eliminating custom COBOL or REXX routines. This in-depth guide explains every major DATE feature in DFSORT 2.x, illustrates best practices, and provides reusable JCL templates.
DATE1, &DATE1, DATE1(c), &DATE1(c), DATE2, &DATE2, DATE2(c), &DATE2(c), DATE3, &DATE3, DATE3(c), &DATE3(c), DATE4, &DATE4, DATE5 or &DATE5 can be used to generate a character string for the current date of the run.
Note: You can precede each of the operands in the table with an & with identical results. When a field is shorter than the character string it’s compared to, DFSORT truncates the string on the right. You can take advantage of this to compare a field to only part of the DATE4 timestamp when appropriate. For example:
INCLUDE COND=(1,13,CH,GT,DATE4)
The above condition will compare the field in positions 1-13 to the truncated DATE4 constant C’yyyy-mm-dd-hh’.
| Family | Keyword | Format | Example | Typical Use |
| Current date | DATE1 | C’yyyymmdd’ | 20250720 | File headers, run-date stamps |
| Current date (Separator) | DATE1(c) C = ‘-‘ | C’yyyy-mm-dd’ | 2025-07-20 | Readable audit files |
| Current month | DATE2 | C’yyyymm’ | 202507 | Monthly partitions |
| Current month (Separator) | DATE2(c) | C’yyyycmm’ | C’2005/06′ | Readable audit files |
| Current Julian | DATE3 | C’yyyyddd’ | 2025201 | Sort keys for daily cycles |
| Current Julian (Seperator) | DATE3(c) | C’yyyycddd’ | C’2005/172′ | Readable audit files |
| Full timestamp | DATE4 | C’yyyy-mm-dd-hh.mm.ss’ | 2025-07-20-13.23.00 | SMF-like logs |
| Full timestamp | DATE5 | C’yyyy-mm-dd-hh.mm.ss.nnnnnn’ | 2005-06-21-16.52.45.582013′ | With timestamp |
Tip: Prepend & to any keyword (e.g., &DATE1) when you need the same constant in multiple steps—DFSORT expands it only once per job
DATE1+d, &DATE1+d, DATE1(c)+d, &DATE1(c)+d, DATE2+m, &DATE2+m, DATE2(c)+m, &DATE2(c)+m, DATE3+d, &DATE3+d, DATE3(c)+d or &DATE3(c)+d can be used to generate a character string for a future date relative to the current date of the run. d is days in the future and m is months in the future. d and m can be 0 to 9999.
DATE1-d, &DATE1-d, DATE1(c)-d, &DATE1(c)-d, DATE2-m, &DATE2-m, DATE2(c)-m, &DATE2(c)-m, DATE3-d, &DATE3-d, DATE3(c)-d or &DATE3(c)-d can be used to generate a character string for a past date relative to the current date of the run. d is days in the future and m is months in the future. d and m can be 0 to 9999.d is days in the future and m is months in the future. d and m can be 0 to 9999.
DATE1P, &DATE1P, DATE2P, &DATE2P, DATE3P, or &DATE3P can be used to generate a decimal number for the current date of the run.
DATE1P+d, &DATE1P+d, DATE2P+m, &DATE2P+m, DATE3P+d, or &DATE3P+d can be used to generate a decimal number for a future date relative to the current date of the run. d is days in the future and m is months in the future. d and m can be 0 to 9999.
DATE1P-d, &DATE1P-d, DATE2P-m, &DATE2P-m, DATE3P-d, or &DATE3P-d can be used to generate a decimal number for a past date relative to the current date of the run. d is days in the past and m is months in the past. d and m can be 0 to 9999.
DFSORT converts any Y4x/Y2x field between Julian and Gregorian. Supported input types include CH, ZD, PD, BI, and UFF. The following job converts a ‘yyyymmdd’ date to a ‘yyyyddd’ date:
INREC BUILD=(1,8,Y4T,TOJUL=Y4T(/))
Input 20090520 becomes 2009/140.
| Operand | Target Form | Result Example |
| TOJUL=Y4T | yyyyddd | 2025201 |
| TOJUL=Y4T(/) | yyyy/ddd | 2025/201 |
| TOGREG=Y4W(-) | mm-dd-yyyy | 07-20-2025 |
OUTREC OVERLAY=(5:5,6,Y2T,TOJUL=Y4T(-))
OUTFIL OVERLAY=(1:1,4,Y4X,TOGREG=Y4W(-))
SORT FIELDS=(1,10,CH,A) OUTREC IFTHEN=(WHEN=INIT,BUILD=(1,10,UFF,TO=ZD,LENGTH=8)), IFTHEN=(WHEN=INIT,BUILD=(1,8,Y4T,TOGREG=Y2Y))
OPTION COPY OUTREC IFTHEN=(WHEN=INIT, BUILD=(1,10,UFF,TO=ZD,LENGTH=8,9:11,3)), IFTHEN=(WHEN=INIT,BUILD=(1,8,Y4W,TOJUL=Y4T,9,3))
OUTFIL REMOVECC,
HEADER1=(DATE=(4MD-),C' DAILY SALES REPORT'),
TRAILER1=(COUNT=(M11,LENGTH=9)) INREC OVERLAY=(40:5,8,Y4T,AGE=YMD) /* 19991231 → 00250120 (25 years 1 month 20 days) */
You can use TOGREG or TOJUL functions to identify invalid input dates. Dates with values outside of the valid range (for example, a month not between 01-12) will be shown as asterisks making them easy to identify.
Example: If you had the following input records with ‘yyyymmdd’ dates:
INPUT: Betten 20091021 Vezinaw 20091101 Casad 00000000 Boenig 20091325 Kolusu 20090931 Yaeger 20090731
You could use below control statements to display an additional column with asterisks for any invalid dates
SYSIN:
OPTION COPY
OUTREC OVERLAY=(30:16,8,Y4T,TOGREG=Y4T)
OUTPUT:
BETTEN 20091021 20091021
VEZINAW 20091101 20091101
CASAD 00000000 00000000
BOENIG 20091325 ********
KOLUSU 20090931 ********
YAEGER 20090731 20090731
If you wanted to display only the records with invalid dates, you could use these control statements:
OPTION COPY OUTREC OVERLAY=30:16,8,Y4T,TOGREG=Y2T) OUTFIL INCLUDE=30,1,CH,EQ,C'*'),BUILD=(1,25)
OUTPUT: BOENIG 20091325 KOLUSU 20090931
Here is an example on how to calculate the number of days between two dates.
INPUT: 20101215 20101105 20110218 20100913 20110127 20110305 SYSIN: OPTION COPY INREC OVERLAY=(20:1,8,Y4T,DATEDIFF,10,8,Y4T)
OUTPUT:
20101215 20101105 +0000040
20110218 20100913 +0000158
20110127 20110305 -0000037
You can use the following date arithmetic functions:
| Keyword | Adds/Subtracts | Supported Units | Example |
| ADDDAYS / SUBDAYS | Days | ±0-32,767 | ADDDAYS,+15 |
| ADDMONS / SUBMONS | Months | ±0-999 | SUBMONS,+3 |
| ADDYEARS / SUBYEARS | Years | ±0-9999 | ADDYEARS,+2 |
| DATENS=(+n,format) | Offset from run date | Days | DATENS=(+30,Y4T) |
INPUT:
20101215
20110110
20110225
SYSIN:
SORT FIELDS=COPY
INREC OVERLAY=(15:1,8,Y4T,ADDDAYS,+15,TOGREG=Y4T(-),
30:1,8,Y4T,SUBDAYS,+23,TOGREG=Y4T(-))
This job adds 15 days to a ‘yyyymmdd’ date in input positions 1-8 and converts the result to a ‘yyyy-mm-dd’ date in output positions 15-24. Subtracts 23 days from a ‘yyyymmdd’ date in input positions 1-8 and converts the result to a ‘yyyy-mm-dd’ date in output positions 30-39.
OUTPUT: 20101215 2010-12-30 2010-11-22 20110110 2011-01-25 2010-12-18 20110225 2011-03-12 2011-02-02
Use the following to calculate the next Friday for a C’ccyyddd’ date as a C’ccyy.ddd’ date: 3,7,Y4T,NEXTDFRI,TOJUL=Y4T(.)
Use the following to calculate the previous Wednesday for a P’yyddd’ date as a C’ccyymmdd’ date: 51,3,Y2U,PREVDWED,TOGREG=Y4T
Use the following to calculate the last day of the month for a C’mmddccyy’ date as a C’mmddccyy’ date: 28,8,Y4W,LASTDAYM,TOGREG=Y4W
This next job subtracts 3 months from a ‘yyddd’ date in input positions 1-5 and converts the result to a ‘dddyyyy’ date in output positions 11-17.
Sort by date, and calculate a specific day after and before a date, and the last day of the quarter for a date. The input date is in the form C’mmddyy’ and the output dates will be in the form ‘ddd-yyyy’.
INPUT:
010105
120699
021610
999999
092810
031500
000000
032505
110210
SYSIN:
OPTION Y2PAST=1990
SORT FIELDS=(1,6,Y2W,A)
OUTFIL REMOVECC, HEADER1=(1:’Input’,15:’NEXTDFRI’,25:’PREVDSUN’,35:’LASTDAYQ’),
BUILD=(1:1,6,Y2W,TOJUL=Y4W(-),
15:1,6,Y2W,NEXTDFRI,TOJUL=Y4W(-),
25:1,6,Y2W,PREVDSUN,TOJUL=Y4W(-),
35:1,6,Y2W,LASTDAYQ,TOJUL=Y4W(-))
OUTPUT:
INPUT NEXTDFRI PREVDSUN LASTDAYQ
000-0000 000-0000 000-0000 000-0000
340-1999 075-2000 001-2005 084-2005
047-2010 271-2010 306-2010 999-9999
344-1999 339-1999 365-1999 077-2000
072-2000 091-2000 007-2005 361-2004
090-2005 091-2005 079-2005 090-2005
050-2010 045-2010 090-2010 274-2010
269-2010 273-2010 309-2010 304-2010
365-2010 999-9999 999-9999 999-9999
Note that the ‘000000’ and ‘999999’ input values are treated as special indicators for output.
INPUT:
10036
11017
11122
SYSIN:
OPTION Y2PAST=1980
SORT FIELDS=(1,5,Y2T,D)
OUTREC BUILD=(1,5,5X,1,5,Y2T,SUBMONS,+3,TOJUL=Y4W)
OUTPUT:
11122 0332011
11017 2902010
10036 3092009
WEEKDAY function can be used to extract the day of the week from various types of dates. Three different output formats for the date are supported as follows:
For example, if you use this job:
INPUT:
07132009
07152009
07172009
SYSIN:
SORT FIELDS=COPY
INREC OVERLAY=(15:1,8,Y4W,WEEKDAY=DIGIT1,X
1,8,Y4W,WEEKDAY=CHAR3,X,
1,8,Y4W,WEEKDAY=CHAR9)
OUTPUT:
07132009 2 MON MONDAY
07152009 4 WED WEDNESDAY
07172009 6 FRI FRIDAY
If you wanted just the CHAR9 result, but with initial capitals, you could use these DFSORT control statements:
SYSIN:
SORT FIELDS=COPY
INREC OVERLAY=(15:1,8,Y4W,WEEKDAY=CHAR9,
16:16,8,TRAN=UTOL)
OUTPUT:
07132009 Monday
07152009 Wednesday
07172009 Friday
Implements tiered storage based on record age
OMIT COND=(32,7,ZD,GT,DATE3-365) Older than 1 year
OUTFIL FILES=01,
INCLUDE=(55,8,CH,LT,DATE1-180), Archive 6+ month old
FILES=02,
INCLUDE=(55,8,CH,GE,DATE1-180) Keep recent
| Message | Cause | Remedy |
| ICE055I 0 FIELD OUT OF RANGE | Wrong starting byte vs. LRECL | Verify positions in hex editor |
| ICE128A KEYWORD INVALID WITH DATASET | Attempted DATE* in SORT FIELDS | Use INREC/OUTREC instead |
| * in converted date | Invalid source date (e.g., 20251301) | Validate input; DFSORT flags with asterisks |
Need a 365-record control dataset for every day of the coming year?
//GENDATE EXEC PGM=SORT
//SYSIN DD *
OPTION COPY
INREC BUILD=(DATE1)
OUTFIL SEQNUM,
SEQNUM=(8,ZD,START=0,INCR=1),
TRAILER1=NONE
/*
//SORTIN DD DUMMY
//SORTOUT DD DSN=CTRL.DAILY.DATES,
// DISP=(NEW,CATLG),LRECL=8,RECFM=FB
DFSORT writes one record: 20250720. Chain a second step to REPEAT=365, ADDDAYS,+1, and you have a full year calendar without a loop.
//STPALL EXEC PGM=SORT
//SYSIN DD *
OPTION COPY
* Add current high-precision timestamp
INREC IFTHEN=(WHEN=INIT,
OVERLAY=(1:DATE5))
* Calculate age duration
INREC IFTHEN=(WHEN=INIT,
OVERLAY=(200:150,8,Y4T,AGE=YMD))
* ISO week number
INREC IFTHEN=(WHEN=INIT,
OVERLAY=(190:150,8,Y4T,WEEKNUM=ISO))
* Reject sign-ups older than two years
OUTFIL INCLUDE=(200,8,ZD,GT,+00200000),
BUILD=(1,*)
/*
//SORTIN DD DSN=APP.CUST.MASTER,DISP=SHR
//SORTOUT DD DSN=APP.CUST.MASTER.AUGMENTED,
// DISP=(NEW,CATLG),SPACE=(CYL,(50,10))
//SYSOUT DD SYSOUT=*
DFSORT’s DATE functions provide industrial-strength tooling for every conceivable batch scheduling, auditing, or calendar-driven requirement. By mastering constants (DATE1-DATE5), conversions (TOJUL/TOGREG), arithmetic (ADD*/SUB*), and analytics (WEEKNUM, AGE, DATEDIFF), you can modernize legacy JCL, reduce CPU cycles, and improve data quality—all without external code. Mainframe SORT utilities provide an exhaustive temporal toolkit that transforms date processing from a logistical challenge into a strategic asset.
As temporal data volumes grow exponentially, these functions form the bedrock of efficient mainframe operations. Future developments will likely integrate machine learning for intelligent date parsing and predictive temporal modeling, further cementing SORT utilities’ role in enterprise data management.
OUTER JOIN Queries are a valuable tool in SQL, allowing you to retrieve data from…
DFSORT is your go‑to utility for sorting, merging, and transforming data. ICETOOL Utilities takes DFSORT…
VSAM REPRO command is used to copy data from one file(Input file) to another file(Output…
The Product Owner role has shifted from just being a requirements proxy to a strategic,…
Business Value: In the world of Agile development, the user story has long been the…
The SAFe Scrum Master certification has become one of the most sought-after credentials for Agile…
The Professional Scrum with Kanban (PSK) course enhances your organization's ability to deliver value efficiently…
Effective User interviews play a crucial role in Scrum methodology, helping Product Owners and Scrum…
Product Owners should be well-versed in various user research tools and techniques to effectively understand…