Date and time handling in COBOL involves obtaining current date/time, formatting dates for display, performing date calculations, validating dates, and working with various date formats. COBOL provides functions like CURRENT-DATE and ACCEPT FROM DATE/TIME to get system date and time, and you use string manipulation and arithmetic to format, calculate, and validate dates. Effective date/time handling is essential for business applications that need timestamps, age calculations, date-based reporting, and temporal data processing.
CURRENT-DATE is the most comprehensive way to get current date and time:
1234567891011121314WORKING-STORAGE SECTION. 01 CURRENT-DATE-TIME PIC X(21). PROCEDURE DIVISION. GET-CURRENT-DATE-TIME. MOVE FUNCTION CURRENT-DATE TO CURRENT-DATE-TIME *> CURRENT-DATE returns: YYYYMMDDHHMMSSssssss+HHMM *> Example: "20240115143045234567+0500" *> 2024-01-15 14:30:45.234567 +05:00 DISPLAY 'Current date/time: ' CURRENT-DATE-TIME STOP RUN.
CURRENT-DATE format breakdown:
123456789101112131415161718WORKING-STORAGE SECTION. 01 CURRENT-DATE-YYYYMMDD PIC 9(8). 01 CURRENT-DATE-YYMMDD PIC 9(6). PROCEDURE DIVISION. GET-DATE-ONLY. *> Get date in YYYYMMDD format ACCEPT CURRENT-DATE-YYYYMMDD FROM DATE YYYYMMDD *> Result: 20240115 *> Get date in YYMMDD format (2-digit year) ACCEPT CURRENT-DATE-YYMMDD FROM DATE YYMMDD *> Result: 240115 DISPLAY 'Date (YYYYMMDD): ' CURRENT-DATE-YYYYMMDD DISPLAY 'Date (YYMMDD): ' CURRENT-DATE-YYMMDD STOP RUN.
123456789101112WORKING-STORAGE SECTION. 01 CURRENT-TIME PIC 9(8). PROCEDURE DIVISION. GET-TIME-ONLY. *> Get time in HHMMSS format ACCEPT CURRENT-TIME FROM TIME *> Result: 143045 (2:30:45 PM) DISPLAY 'Current time: ' CURRENT-TIME STOP RUN.
Use reference modification to extract date parts:
12345678910111213141516171819202122232425262728293031WORKING-STORAGE SECTION. 01 CURRENT-DATE-TIME PIC X(21). 01 DATE-YYYYMMDD PIC 9(8). 01 YEAR PIC 9(4). 01 MONTH PIC 9(2). 01 DAY PIC 9(2). 01 HOUR PIC 9(2). 01 MINUTE PIC 9(2). 01 SECOND PIC 9(2). PROCEDURE DIVISION. EXTRACT-COMPONENTS. MOVE FUNCTION CURRENT-DATE TO CURRENT-DATE-TIME *> Extract date portion (YYYYMMDD) MOVE CURRENT-DATE-TIME(1:8) TO DATE-YYYYMMDD *> Extract individual components MOVE CURRENT-DATE-TIME(1:4) TO YEAR *> 2024 MOVE CURRENT-DATE-TIME(5:2) TO MONTH *> 01 MOVE CURRENT-DATE-TIME(7:2) TO DAY *> 15 MOVE CURRENT-DATE-TIME(9:2) TO HOUR *> 14 MOVE CURRENT-DATE-TIME(11:2) TO MINUTE *> 30 MOVE CURRENT-DATE-TIME(13:2) TO SECOND *> 45 DISPLAY 'Year: ' YEAR DISPLAY 'Month: ' MONTH DISPLAY 'Day: ' DAY DISPLAY 'Time: ' HOUR ':' MINUTE ':' SECOND STOP RUN.
Format dates for display using STRING or reference modification:
1234567891011121314151617181920212223242526272829WORKING-STORAGE SECTION. 01 DATE-YYYYMMDD PIC 9(8). 01 FORMATTED-DATE PIC X(10). 01 YEAR PIC 9(4). 01 MONTH PIC 9(2). 01 DAY PIC 9(2). PROCEDURE DIVISION. FORMAT-US-STYLE. ACCEPT DATE-YYYYMMDD FROM DATE YYYYMMDD *> Extract components MOVE DATE-YYYYMMDD(1:4) TO YEAR MOVE DATE-YYYYMMDD(5:2) TO MONTH MOVE DATE-YYYYMMDD(7:2) TO DAY *> Build MM/DD/YYYY format STRING MONTH DELIMITED BY SIZE '/' DELIMITED BY SIZE DAY DELIMITED BY SIZE '/' DELIMITED BY SIZE YEAR DELIMITED BY SIZE INTO FORMATTED-DATE END-STRING DISPLAY 'Formatted date: ' FORMATTED-DATE *> Output: 01/15/2024 STOP RUN.
123456789101112131415161718192021PROCEDURE DIVISION. FORMAT-EUROPEAN-STYLE. ACCEPT DATE-YYYYMMDD FROM DATE YYYYMMDD MOVE DATE-YYYYMMDD(1:4) TO YEAR MOVE DATE-YYYYMMDD(5:2) TO MONTH MOVE DATE-YYYYMMDD(7:2) TO DAY *> Build DD-MM-YYYY format STRING DAY DELIMITED BY SIZE '-' DELIMITED BY SIZE MONTH DELIMITED BY SIZE '-' DELIMITED BY SIZE YEAR DELIMITED BY SIZE INTO FORMATTED-DATE END-STRING DISPLAY 'Formatted date: ' FORMATTED-DATE *> Output: 15-01-2024 STOP RUN.
Validate dates to ensure they're correct:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869WORKING-STORAGE SECTION. 01 INPUT-DATE PIC 9(8). 01 YEAR PIC 9(4). 01 MONTH PIC 9(2). 01 DAY PIC 9(2). 01 VALID-DATE-FLAG PIC X VALUE 'Y'. 88 VALID-DATE VALUE 'Y'. 88 INVALID-DATE VALUE 'N'. PROCEDURE DIVISION. VALIDATE-DATE. *> Assume INPUT-DATE contains YYYYMMDD format MOVE INPUT-DATE(1:4) TO YEAR MOVE INPUT-DATE(5:2) TO MONTH MOVE INPUT-DATE(7:2) TO DAY *> Check if date is numeric IF INPUT-DATE IS NOT NUMERIC SET INVALID-DATE TO TRUE ELSE *> Check month range IF MONTH < 1 OR MONTH > 12 SET INVALID-DATE TO TRUE ELSE *> Check day range based on month PERFORM CHECK-DAY-VALIDITY END-IF END-IF IF VALID-DATE DISPLAY 'Date is valid' ELSE DISPLAY 'ERROR: Invalid date' END-IF STOP RUN. CHECK-DAY-VALIDITY. *> Check day based on month EVALUATE MONTH WHEN 1 3 5 7 8 10 12 *> Months with 31 days IF DAY < 1 OR DAY > 31 SET INVALID-DATE TO TRUE END-IF WHEN 4 6 9 11 *> Months with 30 days IF DAY < 1 OR DAY > 30 SET INVALID-DATE TO TRUE END-IF WHEN 2 *> February - check for leap year PERFORM CHECK-FEBRUARY-DAY END-EVALUATE. CHECK-FEBRUARY-DAY. IF FUNCTION MOD(YEAR, 4) = 0 AND FUNCTION MOD(YEAR, 100) NOT = 0 OR FUNCTION MOD(YEAR, 400) = 0 *> Leap year - allow day 29 IF DAY < 1 OR DAY > 29 SET INVALID-DATE TO TRUE END-IF ELSE *> Not leap year - max day 28 IF DAY < 1 OR DAY > 28 SET INVALID-DATE TO TRUE END-IF END-IF.
A year is a leap year if it's divisible by 4, except century years which must be divisible by 400:
123456789101112131415161718192021WORKING-STORAGE SECTION. 01 YEAR PIC 9(4). 01 IS-LEAP-YEAR-FLAG PIC X. 88 IS-LEAP-YEAR VALUE 'Y'. 88 NOT-LEAP-YEAR VALUE 'N'. PROCEDURE DIVISION. CHECK-LEAP-YEAR. *> Leap year if: (divisible by 4 AND not century) *> OR (divisible by 400) IF (FUNCTION MOD(YEAR, 4) = 0 AND FUNCTION MOD(YEAR, 100) NOT = 0) OR FUNCTION MOD(YEAR, 400) = 0 SET IS-LEAP-YEAR TO TRUE DISPLAY YEAR ' is a leap year' ELSE SET NOT-LEAP-YEAR TO TRUE DISPLAY YEAR ' is not a leap year' END-IF STOP RUN.
12345678910111213141516171819202122232425262728293031323334WORKING-STORAGE SECTION. 01 START-DATE PIC 9(8) VALUE 20240115. 01 DAYS-TO-ADD PIC 9(4) VALUE 30. 01 RESULT-DATE PIC 9(8). 01 YEAR PIC 9(4). 01 MONTH PIC 9(2). 01 DAY PIC 9(2). PROCEDURE DIVISION. ADD-DAYS. *> Simple approach: add days and handle overflow *> Note: This is simplified - full implementation *> needs to handle month/year boundaries MOVE START-DATE(1:4) TO YEAR MOVE START-DATE(5:2) TO MONTH MOVE START-DATE(7:2) TO DAY ADD DAYS-TO-ADD TO DAY *> Handle day overflow (simplified) *> Full implementation would check month lengths *> and handle year boundaries *> Build result date COMPUTE RESULT-DATE = YEAR * 10000 + MONTH * 100 + DAY DISPLAY 'Start date: ' START-DATE DISPLAY 'Days to add: ' DAYS-TO-ADD DISPLAY 'Result date: ' RESULT-DATE STOP RUN.
| Format | Example | Common Use |
|---|---|---|
| YYYYMMDD | 20240115 | Most common, sortable, compact |
| MM/DD/YYYY | 01/15/2024 | US display format |
| DD/MM/YYYY | 15/01/2024 | European display format |
| YYYY-MM-DD | 2024-01-15 | ISO-like format with separators |
| YYMMDD | 240115 | Legacy 2-digit year format |
Follow these best practices:
Think of date/time handling like reading a clock and calendar:
Just like you can read a clock to get the time, COBOL can get the current date/time and work with it!
1. What does CURRENT-DATE return?
2. How do you extract the year from a YYYYMMDD date?
3. What is the most common date format in mainframe COBOL?
4. How do you get just the current date (not time)?
5. What makes a year a leap year?
6. How do you format a date as MM/DD/YYYY?