MainframeMaster

Julian Dates

A Julian date in mainframe and DFSORT terms is a date stored as year plus day-of-year: YYYYDDD (or YYDDD with a 2-digit year). The DDD part is 001–366: 001 is January 1, 032 is February 1, and 365 (or 366 in a leap year) is December 31. Many legacy systems store dates in this form because it is compact (7 bytes for YYYYDDD), sorts correctly as character, and avoids month/day logic. In DFSORT you use TOJUL to convert a Gregorian (calendar) date to Julian and TOGREG to convert Julian to Gregorian. This page explains the Julian format, how to convert to and from it in INREC and OUTREC, when to use it, and how it fits with the rest of Date & Time Processing (Gregorian formats, date arithmetic, century windowing).

Date & Time Processing
Progress0 of 0 lessons

What Is the Julian Date Format?

The Julian date format used in DFSORT (and many mainframe applications) is not the same as the historical Julian calendar. Here it simply means: year followed by day-of-year. The day-of-year is a number from 001 to 365 (or 366 in a leap year). So there is no separate month and day—just "which day of the year."

Julian date components
PartMeaning
YYYY (or YY)4-digit year (ccyy) or 2-digit year (yy). With 2-digit, century windowing applies.
DDDDay of year: 001 = Jan 1, 032 = Feb 1, 059 = Feb 28, 060 = Feb 29 (leap), 366 = Dec 31 (leap only).

Examples: 2024001 is January 1, 2024. 2024060 is February 29, 2024 (leap year). 2024366 is December 31, 2024. In a non-leap year like 2023, the last day is 2023365; 2023366 would be invalid.

Why Use Julian Dates?

Julian format has several practical advantages on the mainframe:

  • Compact: YYYYDDD is 7 bytes vs 8 for YYYYMMDD. When millions of records store a date, the saving adds up.
  • Sorts correctly: As character data, YYYYDDD orders chronologically. 2024001 is less than 2024366, which is less than 2025001. So SORT FIELDS=(pos,7,CH,A) gives date order.
  • Legacy usage: Many older systems and files already use Julian. Converting to or from it in DFSORT keeps compatibility.
  • No month/day math: Some business logic (e.g. "days since year start") is simpler with day-of-year.

Source Format for Julian Input

When your input is already in Julian form, you must tell DFSORT the format so it can parse and convert it. Use the same format codes as for Gregorian:

Source format for Julian input
CodeMeaning
Y2T2-digit year first: yyddd (5 bytes). Century window applies to yy.
Y4T4-digit year first: ccyyddd (7 bytes). Standard Julian in DFSORT.

So if the input has a 7-byte Julian date at position 41 in ccyyddd form, you specify 41,7,Y4T as the source. If it were 5-byte yyddd, you would use the position, 5, and Y2T. Then you add the conversion operator: TOGREG=Y4T to convert to Gregorian (ccyymmdd) or TOJUL=Y4T to keep or produce Julian (ccyyddd).

Converting Gregorian to Julian (TOJUL)

When the input date is in Gregorian form (e.g. YYYYMMDD or MMDDYYYY), use TOJUL=Y4T (or TOJUL=Y2T for 2-digit year output) to produce Julian. The source format must match the input: Y4T for ccyymmdd, Y4W for mmddccyy, etc.

Example: input has an 8-byte YYYYMMDD at position 50. Convert to 7-byte YYYYDDD and place it at the start of the record for sorting:

text
1
2
INREC BUILD=(1:50,8,Y4T,TOJUL=Y4T,8:1,49,58:51,30) SORT FIELDS=(1,7,CH,A)

Here 1:50,8,Y4T,TOJUL=Y4T means: from input positions 50–57 (8 bytes), interpret as Y4T (ccyymmdd), convert to Julian Y4T (ccyyddd), and place the 7-byte result at output position 1. Then the rest of the record is copied. Sorting on 1,7 as character ascending gives chronological order by the Julian date.

Converting Julian to Gregorian (TOGREG)

When the input is Julian (YYYYDDD) and you need a calendar date (e.g. for a report or to sort by YYYYMMDD), use the matching source format for Julian and TOGREG=Y4T. The source is 7 bytes for Y4T (ccyyddd).

text
1
2
INREC BUILD=(1:41,7,Y4T,TOGREG=Y4T,9:1,40,49:42,35) SORT FIELDS=(1,8,CH,A)

1:41,7,Y4T,TOGREG=Y4T: input 41–47 is ccyyddd (Julian); convert to ccyymmdd (8 bytes) and place at output 1–8. Now SORT FIELDS=(1,8,CH,A) sorts by the Gregorian date. Use INREC when the sort or INCLUDE/OMIT must see the Gregorian value; use OUTREC when you only need it in the final output.

INREC vs OUTREC for Julian Conversion

The same conversion syntax (source format plus TOJUL or TOGREG) works in both INREC and OUTREC. The difference is when it runs:

  • INREC runs before the sort and before INCLUDE/OMIT. So if you convert Julian to Gregorian in INREC and put the result at a fixed position, you can use SORT FIELDS= or INCLUDE/OMIT on that position. Use INREC whenever the converted date must participate in sort or filter logic.
  • OUTREC runs after the sort. Use OUTREC when you only need the converted date in the final output (e.g. display in a report) and do not need to sort or filter by it.

Field Lengths: 7 vs 8 Bytes

Julian TOJUL=Y4T produces 7 bytes (ccyyddd). Gregorian TOGREG=Y4T produces 8 bytes (ccyymmdd). When you build records in INREC or OUTREC, the next output position must account for this. For example, if you put a converted Julian at 1–7, the next field starts at 8; if you put a converted Gregorian at 1–8, the next starts at 9.

Leap Years and Day 366

In a leap year, day 366 is December 31. In a non-leap year, the last day is 365. DFSORT follows the calendar rules for leap years (divisible by 4, with exceptions for century years). Invalid input (e.g. 366 for a non-leap year) may produce incorrect results or errors; validate source data if needed.

Explain It Like I'm Five

Imagine you have a big calendar with 365 (or 366) boxes for the year. Instead of saying "March 15," you say "day number 74" (or whatever number March 15 is). That number is the "day of the year." A Julian date is just: the year, then that day number. So "2024 074" means the 74th day of 2024. Computers like it because it's one number for the day instead of month and day, and when you sort those numbers, the dates come in the right order.

Exercises

  1. What is 2024100 in Gregorian (month and day)?
  2. Your input has Julian at 30,7 (ccyyddd). You need to sort by this date. Do you convert in INREC or OUTREC? What conversion do you use if you want to sort by Gregorian?
  3. Why is YYYYDDD only 7 bytes while YYYYMMDD is 8 bytes?

Quiz

Test Your Knowledge

1. What does the DDD part of YYYYDDD (Julian date) represent?

  • Day of month (01-31)
  • Day of year (001-366)—January 1 is 001, December 31 is 365 or 366
  • Month (01-12)
  • Week number

2. How do you convert a Gregorian date (YYYYMMDD) to Julian (YYYYDDD) in DFSORT?

  • Use TOGREG=Y4T
  • Use TOJUL=Y4T with the source field and format that matches the input (e.g. Y4T for ccyymmdd)
  • Julian conversion is not supported
  • Use DATE= in OUTREC

3. Why might Julian (YYYYDDD) be useful for sorting or comparing dates?

  • It is shorter
  • As character, YYYYDDD orders chronologically: 2024001 < 2024366 < 2025001
  • Only for leap years
  • It is not useful for sorting

4. If your input has Julian date at position 41 (7 bytes, YYYYDDD), and you need to sort by calendar date, what should you do?

  • Sort by 41,7 as-is
  • Convert to Gregorian in INREC (e.g. 41,7,Y4T,TOGREG=Y4T), place result, then SORT FIELDS= on that position
  • Only OUTREC can convert Julian
  • Use INCLUDE instead of sort

5. What is the length of the output when you convert to TOJUL=Y4T vs TOGREG=Y4T?

  • Both are 8 bytes
  • TOJUL=Y4T gives 7 bytes (ccyyddd); TOGREG=Y4T gives 8 bytes (ccyymmdd)
  • Both are 7 bytes
  • It depends on the input