This page is a lookup for the RPGLE date and time built-in functions: what each one takes, what it returns, and the edge cases that cause run-time errors or surprising results. For a worked tutorial that also covers the CEE date APIs and embedded SQL date functions, read ILE RPG Date, Time and Timestamp Handling. The complete list of BIFs is in the RPGLE Built-in Functions Reference.
All examples are free-form RPGLE.
Date and time BIFs at a glance
| BIF | What it does | Returns |
|---|---|---|
%date | Build or convert to a date | A date |
%time | Build or convert to a time | A time |
%timestamp | Build or convert to a timestamp | A timestamp |
%days, %months, %years | A duration to add to or subtract from a date | A duration |
%hours, %minutes, %seconds, %mseconds | A duration to add to or subtract from a time or timestamp | A duration |
%diff | The length of time between two values | Integer |
%subdt | One part of a date, time or timestamp | Integer |
%DATE
Returns a date. With no parameters it returns the current date.
%date({value {: format}})
| Parameter | Meaning |
|---|---|
value | A character, numeric, date or timestamp value to convert. Omit it for today’s date |
format | The format of value, such as *iso or *usa, for character or numeric data. If you omit it, *iso is assumed. Do not give it for a timestamp |
dcl-s today date;
dcl-s fromText date;
dcl-s fromNumber date;
today = %date(); // the current date
fromText = %date('10/05/2026' : *usa); // 2026-10-05
fromNumber = %date(20261005 : *iso); // 2026-10-05
Date formats
A format code tells %date how to read character or numeric data, and tells %char how to write a date.
| Format | Layout | Example |
|---|---|---|
*ISO | yyyy-mm-dd | 2026-10-05 |
*USA | mm/dd/yyyy | 10/05/2026 |
*EUR | dd.mm.yyyy | 05.10.2026 |
*JIS | yyyy-mm-dd | 2026-10-05 |
*YMD | yy/mm/dd | 26/10/05 |
*MDY | mm/dd/yy | 10/05/26 |
*DMY | dd/mm/yy | 05/10/26 |
*JUL | yy/ddd | 26/278 |
The two-digit-year formats (*YMD, *MDY, *DMY, *JUL) cover a limited range of years. Prefer a four-digit-year format for new code.
%TIME and %TIMESTAMP
%time returns a time and %timestamp returns a timestamp. Both return the current value when called with no parameters.
%time({value {: format}})
%timestamp({value})
dcl-s now time;
dcl-s stamp timestamp;
now = %time(); // the current time
stamp = %timestamp(); // the current date and time
%DAYS, %MONTHS and %YEARS
These return a duration, which you add to or subtract from a date. They do not stand alone.
%days(number)
%months(number)
%years(number)
dcl-s start date inz(d'2026-10-05');
dcl-s due date;
due = start + %days(30); // 2026-11-04
due = start + %months(3); // 2027-01-05
due = start - %years(1); // 2025-10-05
The time durations %hours, %minutes, %seconds and %mseconds work the same way with a time or timestamp.
%DIFF
Returns the number of units between two values, as an integer.
%diff(value1 : value2 : unit)
The result is value1 minus value2, so it is negative when value1 is the earlier value. Both values must be the same type, or a timestamp paired with a date or a time, in which case only the matching part of the timestamp is used. For timestamps, an optional fourth parameter sets the number of fractional seconds to return.
| Unit | Meaning | Valid with |
|---|---|---|
*years or *y | Whole years | Date, timestamp |
*months or *m | Whole months | Date, timestamp |
*days or *d | Days | Date, timestamp |
*hours or *h | Hours | Time, timestamp |
*minutes or *mn | Minutes | Time, timestamp |
*seconds or *s | Seconds | Time, timestamp |
*mseconds or *ms | Microseconds | Time, timestamp |
dcl-s startDate date inz(d'2026-10-05');
dcl-s endDate date inz(d'2026-12-25');
dcl-s span int(10);
span = %diff(endDate : startDate : *days); // 81
span = %diff(startDate : endDate : *days); // -81
%SUBDT
Returns one part of a date, time or timestamp as an integer.
%subdt(value : unit {: digits {: decimals}})
dcl-s d date inz(d'2026-10-05');
dcl-s yearPart int(10);
dcl-s monthPart int(10);
yearPart = %subdt(d : *years); // 2026
monthPart = %subdt(d : *months); // 10
The units are the same as for %diff. The optional digits and decimals parameters set the size of the result, which matters mainly for *mseconds.
Worked example: days overdue
A common use of several BIFs together: find how many days an invoice is overdue, and a new due date if it is extended by one month.
dcl-s invoiceDue date inz(d'2026-09-15');
dcl-s today date inz(d'2026-10-05');
dcl-s daysLate int(10);
dcl-s extended date;
daysLate = %diff(today : invoiceDue : *days); // 20
if daysLate > 0;
extended = invoiceDue + %months(1); // 2026-10-15
endif;
%diff is positive here because today is the later value. Reverse the arguments and the result is -20, which is why the sign convention matters when you test daysLate > 0.
Choosing a duration BIF
- Use
%dayswhen the interval is a fixed number of days, such as a 30-day payment term. - Use
%monthswhen the interval follows the calendar, such as “same day next month”. - Use
%yearsfor anniversaries. Remember the leap-day rule above. - Use
%diffrather than subtracting dates by hand. Subtracting two dates directly is an error unless you use%diffor a duration.
Legacy opcodes
Fixed-format code used opcodes for the same jobs. They still compile; use the BIF in new code.
| Fixed-format opcode | Free-form equivalent |
|---|---|
ADDDUR | + with %days, %months, %years or a time duration |
SUBDUR (duration) | - with a duration, or %diff to find the difference |
EXTRCT | %subdt |
TIME | %time() or %timestamp() |
Common mistakes
- Converting character or numeric data with
%dateand no format, so the compiler cannot know how to read it. - Assuming
+ %months(1)always keeps the same day of the month. - Using
%diffwith a unit that does not fit the type. - Reading the sign of
%diffbackwards. The result is the first value minus the second. - Calling
%dateon input you have not validated. An invalid date stops the program with a run-time error.
FAQ
How do I get today’s date in RPGLE?
Assign %date() to a date field. For the current time use %time(), and for both use %timestamp().
How do I count the days between two dates?
Use %diff(laterDate : earlierDate : *days). The result is positive when the first date is later.
How do I add a month to a date?
Add %months(1) to the date. If the day does not exist in the new month, the result is the last day of that month.
Summary
- Read the teaching version, ILE RPG Date, Time and Timestamp Handling, for conversion patterns and the CEE date APIs.
- Check how lengths and types behave in RPGLE Data Types, Lengths and Precision.
- Return to the RPGLE Built-in Functions Reference to find the string and numeric functions, or open the RPGLE String BIFs Reference.