Date & Time Operations in ABAP include date calculations, factory calendars, timestamps and time zone conversion. Modern classes like CL_ABAP_DATFM complement the classic function modules.
Data Types
| Type | Format | Example |
|---|---|---|
| D (DATS) | YYYYMMDD | 20241124 |
| T (TIMS) | HHMMSS | 143052 |
| TIMESTAMPL | YYYYMMDDHHMMSS.sssssss | 20241124143052.1234567 |
| TIMESTAMP | YYYYMMDDHHMMSS | 20241124143052 |
Examples
1. Basic Date Calculations
DATA: lv_date TYPE sy-datum, lv_days TYPE i.
" Current datelv_date = sy-datum.
" Add/subtract dayslv_date = sy-datum + 30. " 30 days laterlv_date = sy-datum - 7. " 7 days earlier
" Difference between dateslv_days = sy-datum - '20240101'.WRITE: / 'Days since start of year:', lv_days.
" Decompose dateDATA: lv_year TYPE n LENGTH 4, lv_month TYPE n LENGTH 2, lv_day TYPE n LENGTH 2.
lv_year = sy-datum(4).lv_month = sy-datum+4(2).lv_day = sy-datum+6(2).
" Assemble datelv_date = |{ lv_year }{ lv_month }{ lv_day }|.2. Month and Year Calculations
DATA: lv_date TYPE sy-datum.
" Add monthsCALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL' EXPORTING date = sy-datum days = 0 months = 3 " 3 months signum = '+' years = 0 IMPORTING calc_date = lv_date.
" Add yearsCALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL' EXPORTING date = sy-datum days = 0 months = 0 signum = '+' years = 1 " 1 year IMPORTING calc_date = lv_date.
" Get month startDATA(lv_month_start) = sy-datum.lv_month_start+6(2) = '01'.
" Get month endCALL FUNCTION 'RP_LAST_DAY_OF_MONTHS' EXPORTING day_in = sy-datum IMPORTING last_day_of_month = lv_date.
" Quarter startDATA(lv_quarter) = ( ( sy-datum+4(2) - 1 ) DIV 3 ) * 3 + 1.DATA(lv_quarter_start) = |{ sy-datum(4) }{ lv_quarter WIDTH = 2 ALIGN = RIGHT PAD = '0' }01|.3. Weekday and Calendar Week
DATA: lv_weekday TYPE p, lv_week TYPE scal-week.
" Weekday (1=Monday, 7=Sunday)CALL FUNCTION 'DAY_IN_WEEK' EXPORTING datum = sy-datum IMPORTING woession = lv_weekday.
CASE lv_weekday. WHEN 1. WRITE: / 'Monday'. WHEN 2. WRITE: / 'Tuesday'. WHEN 3. WRITE: / 'Wednesday'. WHEN 4. WRITE: / 'Thursday'. WHEN 5. WRITE: / 'Friday'. WHEN 6. WRITE: / 'Saturday'. WHEN 7. WRITE: / 'Sunday'.ENDCASE.
" Calendar weekCALL FUNCTION 'DATE_GET_WEEK' EXPORTING date = sy-datum IMPORTING week = lv_week.
WRITE: / 'Calendar week:', lv_week. " Format: YYYYWW4. Factory Calendar
DATA: lv_workdays TYPE i, lv_target_date TYPE sy-datum.
" Working days between two datesCALL FUNCTION 'RKE_SELECT_FACTDAYS_FOR_PERIOD' EXPORTING i_datab = '20240101' i_datbi = '20240131' i_factid = '01' " Factory calendar ID IMPORTING e_factdays = lv_workdays.
WRITE: / 'Working days in January:', lv_workdays.
" Add working daysCALL FUNCTION 'BKK_ADD_WORKINGDAY' EXPORTING i_date = sy-datum i_days = 5 " 5 working days i_calendar_id = '01' IMPORTING e_date = lv_target_date.
WRITE: / 'In 5 working days:', lv_target_date.
" Check if working dayCALL FUNCTION 'DATE_CHECK_WORKINGDAY' EXPORTING date = sy-datum factory_calendar_id = '01' EXCEPTIONS date_after_range = 1 date_before_range = 2 date_invalid = 3 date_no_workingday = 4 factory_calendar_not_found = 5 OTHERS = 6.
IF sy-subrc = 0. WRITE: / 'Today is a working day'.ELSEIF sy-subrc = 4. WRITE: / 'Today is not a working day'.ENDIF.5. Holidays
DATA: lt_holidays TYPE TABLE OF iscal_day.
" Holidays for a yearCALL FUNCTION 'HOLIDAY_GET' EXPORTING holiday_calendar = 'DE' " Holiday calendar date_from = '20240101' date_to = '20241231' TABLES holidays = lt_holidays EXCEPTIONS factory_calendar_not_found = 1 holiday_calendar_not_found = 2 date_has_invalid_format = 3 date_inconsistency = 4 OTHERS = 5.
IF sy-subrc = 0. LOOP AT lt_holidays INTO DATA(ls_holiday). WRITE: / ls_holiday-date, ls_holiday-holiday_text. ENDLOOP.ENDIF.
" Check if holidayCALL FUNCTION 'HOLIDAY_CHECK_AND_GET_INFO' EXPORTING date = sy-datum holiday_calendar_id = 'DE' IMPORTING holiday_found = DATA(lv_is_holiday) EXCEPTIONS OTHERS = 1.
IF lv_is_holiday = abap_true. WRITE: / 'Today is a holiday'.ENDIF.6. Timestamps
DATA: lv_timestamp TYPE timestamp, lv_timestampl TYPE timestampl.
" Current timestampGET TIME STAMP FIELD lv_timestampl.WRITE: / 'Timestamp:', lv_timestampl.
" Create timestamp from date/timeCONVERT DATE sy-datum TIME sy-uzeit INTO TIME STAMP lv_timestamp TIME ZONE sy-zonlo.
" Convert timestamp to date/timeDATA: lv_date TYPE sy-datum, lv_time TYPE sy-uzeit.
CONVERT TIME STAMP lv_timestamp TIME ZONE sy-zonlo INTO DATE lv_date TIME lv_time.
WRITE: / 'Date:', lv_date, 'Time:', lv_time.
" Timestamp differenceDATA: lv_ts1 TYPE timestampl, lv_ts2 TYPE timestampl, lv_diff TYPE timestampl.
GET TIME STAMP FIELD lv_ts1." ... processing ...GET TIME STAMP FIELD lv_ts2.
lv_diff = lv_ts2 - lv_ts1. " Difference in secondsWRITE: / 'Duration:', lv_diff, 'seconds'.7. Time Zones
DATA: lv_timestamp TYPE timestamp, lv_date_utc TYPE sy-datum, lv_time_utc TYPE sy-uzeit, lv_date_loc TYPE sy-datum, lv_time_loc TYPE sy-uzeit.
GET TIME STAMP FIELD lv_timestamp.
" Convert to UTCCONVERT TIME STAMP lv_timestamp TIME ZONE 'UTC' INTO DATE lv_date_utc TIME lv_time_utc.
" Convert to local timeCONVERT TIME STAMP lv_timestamp TIME ZONE sy-zonlo INTO DATE lv_date_loc TIME lv_time_loc.
WRITE: / 'UTC:', lv_date_utc, lv_time_utc.WRITE: / 'Local:', lv_date_loc, lv_time_loc.
" Get time zone from plantSELECT SINGLE tzone FROM t001w WHERE werks = '1000' INTO @DATA(lv_timezone).
CONVERT TIME STAMP lv_timestamp TIME ZONE lv_timezone INTO DATE lv_date_loc TIME lv_time_loc.8. Format Date
DATA: lv_date TYPE sy-datum VALUE '20241124', lv_formatted TYPE string.
" With string templateslv_formatted = |{ lv_date DATE = USER }|. " User formatlv_formatted = |{ lv_date DATE = ISO }|. " 2024-11-24lv_formatted = |{ lv_date DATE = ENVIRONMENT }|. " System format
WRITE: / lv_formatted.
" With function moduleCALL FUNCTION 'CONVERT_DATE_TO_EXTERNAL' EXPORTING date_internal = lv_date IMPORTING date_external = lv_formatted.
" Custom formatlv_formatted = |{ lv_date+6(2) }.{ lv_date+4(2) }.{ lv_date(4) }|." 24.11.20249. Format Time
DATA: lv_time TYPE sy-uzeit VALUE '143052', lv_formatted TYPE string.
" With string templateslv_formatted = |{ lv_time TIME = USER }|.lv_formatted = |{ lv_time TIME = ISO }|. " 14:30:52
" Custom formatlv_formatted = |{ lv_time(2) }:{ lv_time+2(2) }|. " 14:3010. Date Validation
DATA: lv_date TYPE sy-datum VALUE '20240230'. " Invalid: Feb 30
" Check with function moduleCALL FUNCTION 'DATE_CHECK_PLAUSIBILITY' EXPORTING date = lv_date EXCEPTIONS plausibility_check_failed = 1 OTHERS = 2.
IF sy-subrc <> 0. WRITE: / 'Invalid date'.ENDIF.
" Simple checkIF lv_date IS INITIAL OR lv_date = '00000000'. WRITE: / 'Date is empty'.ENDIF.
" Range checkIF lv_date < '19000101' OR lv_date > '99991231'. WRITE: / 'Date outside valid range'.ENDIF.11. Date Helper Class
CLASS zcl_date_helper DEFINITION. PUBLIC SECTION. CLASS-METHODS: add_days IMPORTING iv_date TYPE sy-datum iv_days TYPE i RETURNING VALUE(rv_date) TYPE sy-datum.
CLASS-METHODS: add_months IMPORTING iv_date TYPE sy-datum iv_months TYPE i RETURNING VALUE(rv_date) TYPE sy-datum.
CLASS-METHODS: add_workdays IMPORTING iv_date TYPE sy-datum iv_days TYPE i iv_calendar TYPE scal-fcalid DEFAULT '01' RETURNING VALUE(rv_date) TYPE sy-datum.
CLASS-METHODS: get_month_start IMPORTING iv_date TYPE sy-datum RETURNING VALUE(rv_date) TYPE sy-datum.
CLASS-METHODS: get_month_end IMPORTING iv_date TYPE sy-datum RETURNING VALUE(rv_date) TYPE sy-datum.
CLASS-METHODS: get_quarter IMPORTING iv_date TYPE sy-datum RETURNING VALUE(rv_quarter) TYPE i.
CLASS-METHODS: is_workday IMPORTING iv_date TYPE sy-datum iv_calendar TYPE scal-fcalid DEFAULT '01' RETURNING VALUE(rv_result) TYPE abap_bool.
CLASS-METHODS: get_weekday_name IMPORTING iv_date TYPE sy-datum RETURNING VALUE(rv_name) TYPE string.ENDCLASS.
CLASS zcl_date_helper IMPLEMENTATION. METHOD add_days. rv_date = iv_date + iv_days. ENDMETHOD.
METHOD add_months. CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL' EXPORTING date = iv_date days = 0 months = abs( iv_months ) signum = COND #( WHEN iv_months >= 0 THEN '+' ELSE '-' ) years = 0 IMPORTING calc_date = rv_date. ENDMETHOD.
METHOD add_workdays. CALL FUNCTION 'BKK_ADD_WORKINGDAY' EXPORTING i_date = iv_date i_days = iv_days i_calendar_id = iv_calendar IMPORTING e_date = rv_date EXCEPTIONS OTHERS = 1.
IF sy-subrc <> 0. rv_date = iv_date + iv_days. " Fallback ENDIF. ENDMETHOD.
METHOD get_month_start. rv_date = iv_date. rv_date+6(2) = '01'. ENDMETHOD.
METHOD get_month_end. CALL FUNCTION 'RP_LAST_DAY_OF_MONTHS' EXPORTING day_in = iv_date IMPORTING last_day_of_month = rv_date. ENDMETHOD.
METHOD get_quarter. rv_quarter = ( ( iv_date+4(2) - 1 ) DIV 3 ) + 1. ENDMETHOD.
METHOD is_workday. CALL FUNCTION 'DATE_CHECK_WORKINGDAY' EXPORTING date = iv_date factory_calendar_id = iv_calendar EXCEPTIONS date_no_workingday = 4 OTHERS = 1.
rv_result = xsdbool( sy-subrc = 0 ). ENDMETHOD.
METHOD get_weekday_name. DATA: lv_day TYPE p.
CALL FUNCTION 'DAY_IN_WEEK' EXPORTING datum = iv_date IMPORTING woession = lv_day.
rv_name = SWITCH #( lv_day WHEN 1 THEN 'Monday' WHEN 2 THEN 'Tuesday' WHEN 3 THEN 'Wednesday' WHEN 4 THEN 'Thursday' WHEN 5 THEN 'Friday' WHEN 6 THEN 'Saturday' WHEN 7 THEN 'Sunday' ). ENDMETHOD.ENDCLASS.
" UsageDATA(lv_next_month) = zcl_date_helper=>add_months( iv_date = sy-datum iv_months = 1 ).DATA(lv_month_end) = zcl_date_helper=>get_month_end( sy-datum ).DATA(lv_weekday) = zcl_date_helper=>get_weekday_name( sy-datum ).
WRITE: / 'Next month:', lv_next_month, / 'Month end:', lv_month_end, / 'Weekday:', lv_weekday.12. Calculate Time Difference
" Seconds between two time pointsDATA: lv_date1 TYPE sy-datum VALUE '20240101', lv_time1 TYPE sy-uzeit VALUE '080000', lv_date2 TYPE sy-datum VALUE '20240102', lv_time2 TYPE sy-uzeit VALUE '170000', lv_seconds TYPE i.
" Calculate as timestampsDATA: lv_ts1 TYPE timestamp, lv_ts2 TYPE timestamp.
CONVERT DATE lv_date1 TIME lv_time1 INTO TIME STAMP lv_ts1 TIME ZONE 'UTC'.
CONVERT DATE lv_date2 TIME lv_time2 INTO TIME STAMP lv_ts2 TIME ZONE 'UTC'.
lv_seconds = cl_abap_tstmp=>subtract( tstmp1 = lv_ts2 tstmp2 = lv_ts1).
DATA(lv_hours) = lv_seconds / 3600.WRITE: / 'Difference:', lv_hours, 'hours'.13. Performance Measurement
DATA: lv_start TYPE timestampl, lv_end TYPE timestampl, lv_runtime TYPE p DECIMALS 3.
GET TIME STAMP FIELD lv_start.
" Execute codeLOOP AT lt_data INTO DATA(ls_data). " Processing...ENDLOOP.
GET TIME STAMP FIELD lv_end.
" Runtime in secondslv_runtime = cl_abap_tstmp=>subtract( tstmp1 = lv_end tstmp2 = lv_start).
WRITE: / 'Runtime:', lv_runtime, 'seconds'.14. SQL Date Functions
" Modern Open SQL with date functionsSELECT vbeln, erdat, DATS_DAYS_BETWEEN( erdat, @sy-datum ) AS days_ago, DATS_ADD_DAYS( erdat, 30 ) AS plus_30, DATS_ADD_MONTHS( erdat, 1 ) AS plus_month FROM vbak WHERE erdat >= DATS_ADD_DAYS( @sy-datum, -365 ) INTO TABLE @DATA(lt_orders).
" Group by monthSELECT EXTRACT( YEAR FROM erdat ) AS year, EXTRACT( MONTH FROM erdat ) AS month, COUNT(*) AS count, SUM( netwr ) AS total FROM vbak GROUP BY EXTRACT( YEAR FROM erdat ), EXTRACT( MONTH FROM erdat ) INTO TABLE @DATA(lt_monthly).15. Date in RAP
" CDS View with date calculations@AbapCatalog.viewEnhancementCategory: [#NONE]define view entity ZI_OrderDates as select from vbak{ key vbeln, erdat,
@Semantics.systemDate.createdAt: true erdat as CreatedAt,
// Calculated fields dats_days_between(erdat, $session.system_date) as DaysAgo, dats_add_days(erdat, 30) as DueDate}Important Function Modules
| Function Module | Description |
|---|---|
RP_CALC_DATE_IN_INTERVAL | Add months/years |
RP_LAST_DAY_OF_MONTHS | Month end |
DATE_GET_WEEK | Calendar week |
DAY_IN_WEEK | Weekday |
HOLIDAY_GET | Holidays |
DATE_CHECK_WORKINGDAY | Check working day |
BKK_ADD_WORKINGDAY | Add working days |
Important Notes / Best Practice
- sy-datum/sy-uzeit only for current time, do not manipulate.
- Timestamps for precise time measurement and time zones.
- Factory calendar for business logic with working days.
- GET TIME STAMP instead of sy-uzeit for precision.
- UTC for storage, local time for display.
- String templates for formatting:
|{ date DATE = ISO }|. - Date functions in SQL available from ABAP 7.50.
- Validation before calculations.
- Combine with Built-in Functions for more operations.