COBOL provides comprehensive date handling capabilities through intrinsic functions, ACCEPT statements, and date arithmetic operations for modern date processing requirements.
123456789*> Basic date/time retrieval ACCEPT WS-DATE FROM DATE *> YYMMDD format ACCEPT WS-DATE-YYYYMMDD FROM DATE YYYYMMDD *> YYYYMMDD format ACCEPT WS-TIME FROM TIME *> HHMMSSTT format ACCEPT WS-DAY FROM DAY *> YYDDD format ACCEPT WS-DAY-YYYYDDD FROM DAY YYYYDDD *> YYYYDDD format *> Comprehensive date/time information ACCEPT WS-CURRENT-DATE FROM DATE-TIME *> 21-byte format
123456789101112131415161718192021222324252627282930313233WORKING-STORAGE SECTION. 01 WS-CURRENT-DATE-TIME PIC X(21). 01 WS-FORMATTED-DATE PIC X(10). 01 WS-FORMATTED-TIME PIC X(8). 01 WS-INTEGER-DATE PIC 9(7). PROCEDURE DIVISION. GET-CURRENT-DATE-INFO. *> Get complete date/time information MOVE FUNCTION CURRENT-DATE TO WS-CURRENT-DATE-TIME *> Extract components (YYYYMMDDHHMMSSTT+HHMM) MOVE WS-CURRENT-DATE-TIME(1:4) TO WS-YEAR MOVE WS-CURRENT-DATE-TIME(5:2) TO WS-MONTH MOVE WS-CURRENT-DATE-TIME(7:2) TO WS-DAY MOVE WS-CURRENT-DATE-TIME(9:2) TO WS-HOUR MOVE WS-CURRENT-DATE-TIME(11:2) TO WS-MINUTE MOVE WS-CURRENT-DATE-TIME(13:2) TO WS-SECOND *> Format for display STRING WS-MONTH "/" WS-DAY "/" WS-YEAR DELIMITED BY SIZE INTO WS-FORMATTED-DATE STRING WS-HOUR ":" WS-MINUTE ":" WS-SECOND DELIMITED BY SIZE INTO WS-FORMATTED-TIME *> Get integer date (days since 1601-01-01) COMPUTE WS-INTEGER-DATE = FUNCTION INTEGER-OF-DATE( FUNCTION NUMVAL(WS-CURRENT-DATE-TIME(1:8))) DISPLAY "Current Date: " WS-FORMATTED-DATE DISPLAY "Current Time: " WS-FORMATTED-TIME DISPLAY "Integer Date: " WS-INTEGER-DATE.
123456789101112131415161718192021222324252627282930WORKING-STORAGE SECTION. 01 WS-INPUT-DATE PIC 9(8) VALUE 20231215. 01 WS-INTEGER-DATE PIC 9(7). 01 WS-DAY-OF-YEAR PIC 9(3). 01 WS-DAY-OF-WEEK PIC 9. 01 WS-FORMATTED-DATE PIC X(10). PROCEDURE DIVISION. DATE-CONVERSION-EXAMPLE. *> Convert YYYYMMDD to integer date COMPUTE WS-INTEGER-DATE = FUNCTION INTEGER-OF-DATE(WS-INPUT-DATE) DISPLAY "Integer date: " WS-INTEGER-DATE *> Convert integer date back to YYYYMMDD COMPUTE WS-INPUT-DATE = FUNCTION DATE-OF-INTEGER(WS-INTEGER-DATE) DISPLAY "Date from integer: " WS-INPUT-DATE *> Get day of year (Julian date) COMPUTE WS-DAY-OF-YEAR = FUNCTION DAY-OF-INTEGER(WS-INTEGER-DATE) DISPLAY "Day of year: " WS-DAY-OF-YEAR *> Get day of week (1=Monday, 7=Sunday) COMPUTE WS-DAY-OF-WEEK = FUNCTION MOD(WS-INTEGER-DATE, 7) + 1 DISPLAY "Day of week: " WS-DAY-OF-WEEK *> Format date for display STRING WS-INPUT-DATE(5:2) "/" WS-INPUT-DATE(7:2) "/" WS-INPUT-DATE(1:4) DELIMITED BY SIZE INTO WS-FORMATTED-DATE DISPLAY "Formatted date: " WS-FORMATTED-DATE.
1234567891011121314151617181920212223242526272829303132333435363738WORKING-STORAGE SECTION. 01 WS-START-DATE PIC 9(8) VALUE 20231201. 01 WS-END-DATE PIC 9(8). 01 WS-DAYS-TO-ADD PIC 9(3) VALUE 30. 01 WS-INTEGER-START PIC 9(7). 01 WS-INTEGER-END PIC 9(7). 01 WS-DAYS-DIFFERENCE PIC S9(5). PROCEDURE DIVISION. DATE-ARITHMETIC-EXAMPLE. *> Convert start date to integer COMPUTE WS-INTEGER-START = FUNCTION INTEGER-OF-DATE(WS-START-DATE) *> Add days to get end date COMPUTE WS-INTEGER-END = WS-INTEGER-START + WS-DAYS-TO-ADD COMPUTE WS-END-DATE = FUNCTION DATE-OF-INTEGER(WS-INTEGER-END) DISPLAY "Start date: " WS-START-DATE DISPLAY "Days to add: " WS-DAYS-TO-ADD DISPLAY "End date: " WS-END-DATE *> Calculate difference between two dates COMPUTE WS-DAYS-DIFFERENCE = WS-INTEGER-END - WS-INTEGER-START DISPLAY "Days difference: " WS-DAYS-DIFFERENCE. CALCULATE-AGE-IN-DAYS. *> Calculate age in days 01 WS-BIRTH-DATE PIC 9(8) VALUE 19900515. 01 WS-CURRENT-DATE-NUM PIC 9(8). 01 WS-AGE-DAYS PIC 9(5). ACCEPT WS-CURRENT-DATE-NUM FROM DATE YYYYMMDD COMPUTE WS-AGE-DAYS = FUNCTION INTEGER-OF-DATE(WS-CURRENT-DATE-NUM) - FUNCTION INTEGER-OF-DATE(WS-BIRTH-DATE) DISPLAY "Age in days: " WS-AGE-DAYS.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768WORKING-STORAGE SECTION. 01 WS-INVOICE-DATE PIC 9(8). 01 WS-DUE-DATE PIC 9(8). 01 WS-PAYMENT-TERMS PIC 9(2) VALUE 30. 01 WS-WEEKEND-DAYS PIC 9(2) VALUE ZERO. 01 WS-WORK-DATE PIC 9(8). 01 WS-DAY-OF-WEEK PIC 9. PROCEDURE DIVISION. CALCULATE-DUE-DATE. ACCEPT WS-INVOICE-DATE FROM DATE YYYYMMDD *> Add payment terms to invoice date COMPUTE WS-DUE-DATE = FUNCTION DATE-OF-INTEGER( FUNCTION INTEGER-OF-DATE(WS-INVOICE-DATE) + WS-PAYMENT-TERMS) *> Adjust for weekends (move to next Monday if weekend) PERFORM ADJUST-FOR-WEEKEND DISPLAY "Invoice Date: " WS-INVOICE-DATE DISPLAY "Payment Terms: " WS-PAYMENT-TERMS " days" DISPLAY "Due Date: " WS-DUE-DATE. ADJUST-FOR-WEEKEND. MOVE WS-DUE-DATE TO WS-WORK-DATE *> Get day of week (1=Monday, 7=Sunday) COMPUTE WS-DAY-OF-WEEK = FUNCTION MOD( FUNCTION INTEGER-OF-DATE(WS-WORK-DATE), 7) + 1 *> If Saturday (6) or Sunday (7), move to Monday IF WS-DAY-OF-WEEK = 6 ADD 2 TO WS-WORK-DATE ELSE IF WS-DAY-OF-WEEK = 7 ADD 1 TO WS-WORK-DATE END-IF MOVE WS-WORK-DATE TO WS-DUE-DATE. CALCULATE-BUSINESS-DAYS. *> Calculate business days between two dates 01 WS-START-BUS-DATE PIC 9(8) VALUE 20231201. 01 WS-END-BUS-DATE PIC 9(8) VALUE 20231215. 01 WS-BUSINESS-DAYS PIC 9(3) VALUE ZERO. 01 WS-CURRENT-DATE PIC 9(8). 01 WS-CURRENT-INTEGER PIC 9(7). 01 WS-END-INTEGER PIC 9(7). COMPUTE WS-CURRENT-INTEGER = FUNCTION INTEGER-OF-DATE(WS-START-BUS-DATE) COMPUTE WS-END-INTEGER = FUNCTION INTEGER-OF-DATE(WS-END-BUS-DATE) PERFORM UNTIL WS-CURRENT-INTEGER > WS-END-INTEGER COMPUTE WS-CURRENT-DATE = FUNCTION DATE-OF-INTEGER(WS-CURRENT-INTEGER) COMPUTE WS-DAY-OF-WEEK = FUNCTION MOD(WS-CURRENT-INTEGER, 7) + 1 *> Count only weekdays (Monday=1 to Friday=5) IF WS-DAY-OF-WEEK >= 1 AND WS-DAY-OF-WEEK <= 5 ADD 1 TO WS-BUSINESS-DAYS END-IF ADD 1 TO WS-CURRENT-INTEGER END-PERFORM DISPLAY "Business days: " WS-BUSINESS-DAYS.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475WORKING-STORAGE SECTION. 01 WS-INPUT-DATE PIC 9(8). 01 WS-VALID-DATE-FLAG PIC X VALUE 'Y'. 01 WS-YEAR PIC 9(4). 01 WS-MONTH PIC 9(2). 01 WS-DAY PIC 9(2). 01 WS-LEAP-YEAR-FLAG PIC X. 01 WS-DAYS-IN-MONTH PIC 9(2). PROCEDURE DIVISION. VALIDATE-DATE. MOVE 'Y' TO WS-VALID-DATE-FLAG *> Extract date components MOVE WS-INPUT-DATE(1:4) TO WS-YEAR MOVE WS-INPUT-DATE(5:2) TO WS-MONTH MOVE WS-INPUT-DATE(7:2) TO WS-DAY *> Validate year (reasonable range) IF WS-YEAR < 1900 OR WS-YEAR > 2100 MOVE 'N' TO WS-VALID-DATE-FLAG DISPLAY "Invalid year: " WS-YEAR END-IF *> Validate month IF WS-MONTH < 1 OR WS-MONTH > 12 MOVE 'N' TO WS-VALID-DATE-FLAG DISPLAY "Invalid month: " WS-MONTH END-IF *> Validate day PERFORM GET-DAYS-IN-MONTH IF WS-DAY < 1 OR WS-DAY > WS-DAYS-IN-MONTH MOVE 'N' TO WS-VALID-DATE-FLAG DISPLAY "Invalid day: " WS-DAY END-IF *> Try COBOL intrinsic function validation IF WS-VALID-DATE-FLAG = 'Y' EVALUATE TRUE WHEN FUNCTION TEST-DATE-YYYYMMDD(WS-INPUT-DATE) = 0 DISPLAY "Date is valid: " WS-INPUT-DATE WHEN OTHER MOVE 'N' TO WS-VALID-DATE-FLAG DISPLAY "Date failed intrinsic validation" END-EVALUATE END-IF. GET-DAYS-IN-MONTH. EVALUATE WS-MONTH WHEN 1 OR 3 OR 5 OR 7 OR 8 OR 10 OR 12 MOVE 31 TO WS-DAYS-IN-MONTH WHEN 4 OR 6 OR 9 OR 11 MOVE 30 TO WS-DAYS-IN-MONTH WHEN 2 PERFORM CHECK-LEAP-YEAR IF WS-LEAP-YEAR-FLAG = 'Y' MOVE 29 TO WS-DAYS-IN-MONTH ELSE MOVE 28 TO WS-DAYS-IN-MONTH END-IF END-EVALUATE. CHECK-LEAP-YEAR. MOVE 'N' TO WS-LEAP-YEAR-FLAG IF FUNCTION MOD(WS-YEAR, 4) = 0 IF FUNCTION MOD(WS-YEAR, 100) = 0 IF FUNCTION MOD(WS-YEAR, 400) = 0 MOVE 'Y' TO WS-LEAP-YEAR-FLAG END-IF ELSE MOVE 'Y' TO WS-LEAP-YEAR-FLAG END-IF END-IF.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970WORKING-STORAGE SECTION. 01 WS-INPUT-DATE PIC 9(8) VALUE 20231215. 01 WS-FORMATTED-DATES. 05 WS-US-FORMAT PIC X(10). *> MM/DD/YYYY 05 WS-EURO-FORMAT PIC X(10). *> DD/MM/YYYY 05 WS-ISO-FORMAT PIC X(10). *> YYYY-MM-DD 05 WS-LONG-FORMAT PIC X(25). *> December 15, 2023 01 WS-MONTH-NAMES. 05 FILLER PIC X(9) VALUE "January ". 05 FILLER PIC X(9) VALUE "February ". 05 FILLER PIC X(9) VALUE "March ". 05 FILLER PIC X(9) VALUE "April ". 05 FILLER PIC X(9) VALUE "May ". 05 FILLER PIC X(9) VALUE "June ". 05 FILLER PIC X(9) VALUE "July ". 05 FILLER PIC X(9) VALUE "August ". 05 FILLER PIC X(9) VALUE "September". 05 FILLER PIC X(9) VALUE "October ". 05 FILLER PIC X(9) VALUE "November ". 05 FILLER PIC X(9) VALUE "December ". 01 WS-MONTH-TABLE REDEFINES WS-MONTH-NAMES. 05 WS-MONTH-NAME PIC X(9) OCCURS 12 TIMES. PROCEDURE DIVISION. FORMAT-DATE-EXAMPLES. *> US Format (MM/DD/YYYY) STRING WS-INPUT-DATE(5:2) "/" WS-INPUT-DATE(7:2) "/" WS-INPUT-DATE(1:4) DELIMITED BY SIZE INTO WS-US-FORMAT *> European Format (DD/MM/YYYY) STRING WS-INPUT-DATE(7:2) "/" WS-INPUT-DATE(5:2) "/" WS-INPUT-DATE(1:4) DELIMITED BY SIZE INTO WS-EURO-FORMAT *> ISO Format (YYYY-MM-DD) STRING WS-INPUT-DATE(1:4) "-" WS-INPUT-DATE(5:2) "-" WS-INPUT-DATE(7:2) DELIMITED BY SIZE INTO WS-ISO-FORMAT *> Long Format (Month DD, YYYY) STRING WS-MONTH-NAME(FUNCTION NUMVAL(WS-INPUT-DATE(5:2))) DELIMITED BY SPACE WS-INPUT-DATE(7:2) ", " WS-INPUT-DATE(1:4) DELIMITED BY SIZE INTO WS-LONG-FORMAT DISPLAY "Original: " WS-INPUT-DATE DISPLAY "US Format: " WS-US-FORMAT DISPLAY "Euro Format: " WS-EURO-FORMAT DISPLAY "ISO Format: " WS-ISO-FORMAT DISPLAY "Long Format: " WS-LONG-FORMAT. PARSE-DATE-FROM-STRING. *> Parse various date formats 01 WS-DATE-STRING PIC X(10) VALUE "12/15/2023". 01 WS-PARSED-DATE PIC 9(8). 01 WS-MONTH-STR PIC X(2). 01 WS-DAY-STR PIC X(2). 01 WS-YEAR-STR PIC X(4). *> Parse MM/DD/YYYY format UNSTRING WS-DATE-STRING DELIMITED BY "/" INTO WS-MONTH-STR, WS-DAY-STR, WS-YEAR-STR STRING WS-YEAR-STR WS-MONTH-STR WS-DAY-STR DELIMITED BY SIZE INTO WS-PARSED-DATE DISPLAY "Parsed date: " WS-PARSED-DATE.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152WORKING-STORAGE SECTION. 01 WS-BIRTH-DATE PIC 9(8) VALUE 19850315. 01 WS-CURRENT-DATE PIC 9(8). 01 WS-AGE-YEARS PIC 9(3). 01 WS-AGE-MONTHS PIC 9(2). 01 WS-AGE-DAYS PIC 9(2). 01 WS-TEMP-DATE PIC 9(8). PROCEDURE DIVISION. CALCULATE-PRECISE-AGE. ACCEPT WS-CURRENT-DATE FROM DATE YYYYMMDD *> Calculate years COMPUTE WS-AGE-YEARS = WS-CURRENT-DATE(1:4) - WS-BIRTH-DATE(1:4) *> Adjust if birthday hasn't occurred this year IF WS-CURRENT-DATE(5:4) < WS-BIRTH-DATE(5:4) SUBTRACT 1 FROM WS-AGE-YEARS END-IF *> Calculate months and days for more precision PERFORM CALCULATE-MONTHS-DAYS DISPLAY "Birth Date: " WS-BIRTH-DATE DISPLAY "Current Date: " WS-CURRENT-DATE DISPLAY "Age: " WS-AGE-YEARS " years, " WS-AGE-MONTHS " months, " WS-AGE-DAYS " days". CALCULATE-MONTHS-DAYS. *> Build anniversary date for this year STRING WS-CURRENT-DATE(1:4) WS-BIRTH-DATE(5:4) DELIMITED BY SIZE INTO WS-TEMP-DATE *> If anniversary hasn't passed, use last year IF WS-CURRENT-DATE < WS-TEMP-DATE COMPUTE WS-TEMP-DATE = WS-TEMP-DATE - 10000 END-IF *> Calculate remaining months and days COMPUTE WS-AGE-MONTHS = WS-CURRENT-DATE(5:2) - WS-TEMP-DATE(5:2) COMPUTE WS-AGE-DAYS = WS-CURRENT-DATE(7:2) - WS-TEMP-DATE(7:2) *> Adjust for negative days IF WS-AGE-DAYS < 0 SUBTRACT 1 FROM WS-AGE-MONTHS ADD 30 TO WS-AGE-DAYS *> Approximate END-IF *> Adjust for negative months IF WS-AGE-MONTHS < 0 ADD 12 TO WS-AGE-MONTHS END-IF.
12345678910111213141516171819202122232425262728293031323334353637383940WORKING-STORAGE SECTION. 01 WS-START-DATE PIC 9(8) VALUE 20231201. 01 WS-END-DATE PIC 9(8) VALUE 20231231. 01 WS-CURRENT-PROCESS-DATE PIC 9(8). 01 WS-PROCESS-COUNT PIC 9(5) VALUE ZERO. 01 WS-WEEKEND-COUNT PIC 9(3) VALUE ZERO. 01 WS-WEEKDAY-COUNT PIC 9(3) VALUE ZERO. PROCEDURE DIVISION. PROCESS-DATE-RANGE. MOVE WS-START-DATE TO WS-CURRENT-PROCESS-DATE PERFORM UNTIL WS-CURRENT-PROCESS-DATE > WS-END-DATE ADD 1 TO WS-PROCESS-COUNT *> Check if weekend IF FUNCTION MOD(FUNCTION INTEGER-OF-DATE( WS-CURRENT-PROCESS-DATE), 7) + 1 > 5 ADD 1 TO WS-WEEKEND-COUNT ELSE ADD 1 TO WS-WEEKDAY-COUNT END-IF *> Process business logic for this date PERFORM PROCESS-SINGLE-DATE *> Move to next date COMPUTE WS-CURRENT-PROCESS-DATE = FUNCTION DATE-OF-INTEGER( FUNCTION INTEGER-OF-DATE(WS-CURRENT-PROCESS-DATE) + 1) END-PERFORM DISPLAY "Date range processed: " WS-START-DATE " to " WS-END-DATE DISPLAY "Total days: " WS-PROCESS-COUNT DISPLAY "Weekdays: " WS-WEEKDAY-COUNT DISPLAY "Weekend days: " WS-WEEKEND-COUNT. PROCESS-SINGLE-DATE. *> Example: Log processing for each date DISPLAY "Processing date: " WS-CURRENT-PROCESS-DATE.
DATE returns a 6-digit format (YYMMDD) which can cause Y2K issues, while DATE YYYYMMDD returns an 8-digit format (YYYYMMDD) that includes the full century and is Y2K compliant.
Convert dates to integer format using INTEGER-OF-DATE, perform arithmetic operations on the integers, then convert back using DATE-OF-INTEGER. This handles leap years and month boundaries automatically.
Use the TEST-DATE-YYYYMMDD intrinsic function which returns 0 for valid dates and non-zero for invalid dates. You can also implement manual validation by checking year, month, and day ranges including leap year considerations.
Standardize on YYYYMMDD format internally for calculations, then use STRING and UNSTRING operations to convert between different display formats as needed. This approach ensures consistent date processing.