Dates and times — eight characters you can subtract¶
Level: 201 · working knowledge
One line: TYPE d is a CHAR(8) holding YYYYMMDD and arithmetic on it counts days, TYPE t is a CHAR(6) holding HHMMSS counting seconds, both can hold values that are not dates at all, and the moment a time zone is involved neither of them is enough.
Dates are text you can do arithmetic on¶
DATA(lv_today) = sy-datum.
DATA(lv_in_30) = CONV d( lv_today + 30 ).
DATA(lv_days) = lv_in_30 - lv_today. " 30
Adding to a date adds days, and subtracting two dates gives days — month ends, leap years and all. That is genuinely convenient and it is also the source of the type's weakness: the underlying storage is characters, so lv_date = '20261332' is accepted and only fails later, somewhere else.
Offsets work for the same reason: lv_today(4) is the year, lv_today+4(2) the month. Reaching for them is normal ABAP; the alternative is a conversion function, not a nicer accessor.
The initial value of a date is '00000000' — not a null, because ABAP has none. Test with IS INITIAL, not against a literal, and be aware that a "no end date" convention in SAP data is usually '99991231' rather than an initial value.
sy-datum is a local date¶
sy-datum and sy-uzeit are the application server's date and time in the user's time zone. Two users in different zones running the same report at the same moment can get different dates, and a job running at 23:00 in one system posts to a different day than the same job in another.
A timestamp is the unambiguous type: TIMESTAMP (P of 14 digits, YYYYMMDDHHMMSS) or TIMESTAMPL with fractional seconds, both in UTC.
GET TIME STAMP FIELD DATA(lv_stamp).
CONVERT TIME STAMP lv_stamp TIME ZONE sy-zonlo
INTO DATE DATA(lv_date) TIME DATA(lv_time).
The zone has to be named to get back to a date, and which zone is a business decision: the user's, the plant's, the company code's, or UTC. Getting it wrong is a whole class of month-end bug that only appears near midnight.
The factory calendar exists for a reason¶
"Thirty days from now" is arithmetic. "Thirty working days from now" is not: it needs the factory calendar, which knows the holidays for a plant and a country. FIMA_DATE_CREATE, DATE_CONVERT_TO_FACTORYDATE and the CL_SCAL_* classes are the usual doors. Anything that computes a due date, a payment term or a delivery date and does not mention a calendar is almost certainly wrong somewhere.
z_tp_dates.prog.abap — pasted here by tools/check_examples.py. Syntax-checked, never run: abaplint parses and type-checks it against the release in abaplint.json, but no system has produced output for it, so this page shows none.
REPORT z_tp_dates.
" TYPE d is eight characters, YYYYMMDD, and arithmetic on it counts DAYS.
DATA(lv_today) = sy-datum.
DATA(lv_in_30) = CONV d( lv_today + 30 ).
DATA(lv_days) = lv_in_30 - lv_today.
WRITE: / 'today ', lv_today.
WRITE: / 'in 30 days', lv_in_30.
WRITE: / 'difference', lv_days.
" Offsets work because the type is really a character field. This is also why
" a date can hold nonsense: nothing stops you writing '20261332' into it.
WRITE: / 'year ', lv_today(4).
WRITE: / 'month ', lv_today+4(2).
WRITE: / 'day ', lv_today+6(2).
" sy-datum is the application server's date in the user's time zone; a
" timestamp is the unambiguous one, and it needs a zone to become a date again.
GET TIME STAMP FIELD DATA(lv_stamp).
CONVERT TIME STAMP lv_stamp TIME ZONE sy-zonlo
INTO DATE DATA(lv_local_date) TIME DATA(lv_local_time).
WRITE: / 'stamp ', lv_stamp.
WRITE: / 'local date', lv_local_date.
WRITE: / 'local time', lv_local_time.
" The initial value of a date is '00000000' -- not a null, and not a date. Test
" for it with IS INITIAL rather than comparing to a literal.
DATA lv_empty TYPE d.
IF lv_empty IS INITIAL.
WRITE: / 'an unset date is initial, not null'.
ENDIF.
If you are coming from another language¶
- Python.
datetime.daterefuses to hold2026-13-32; ABAP'sdaccepts it. Python'stimedeltais ABAP's plain integer arithmetic. - Java.
LocalDateversusInstantis exactly ABAP'sdversusTIMESTAMP, including the rule that the second one needs a zone to become the first. - SQL. A
DATEcolumn is validated by the database; ABAP's type is not, which is why invalid dates survive in tables that have been through an old interface.
See also¶
- Numbers and currency — the other family of types with hidden conventions
- Open SQL — date ranges in a
WHERE, andSELECT-OPTIONS - Background jobs — where "today" is decided by the server, not the user
PARAMETERSandSELECT-OPTIONS— date ranges on a selection screen- Asking what time it is —
GET TIME,GET RUN TIME, and theWAITthat commits - Types at a glance — every elementary type, with a program