Date & Time Operations in ABAP umfassen Datumsberechnungen, Fabrikkalender, Timestamps und Zeitzonenkonvertierung. Moderne Klassen wie CL_ABAP_DATFM ergänzen die klassischen Funktionsbausteine.
Datentypen
| Typ | Format | Beispiel |
|---|---|---|
| D (DATS) | YYYYMMDD | 20241124 |
| T (TIMS) | HHMMSS | 143052 |
| TIMESTAMPL | YYYYMMDDHHMMSS.sssssss | 20241124143052.1234567 |
| TIMESTAMP | YYYYMMDDHHMMSS | 20241124143052 |
Beispiele
1. Grundlegende Datumsberechnungen
DATA: lv_date TYPE sy-datum, lv_days TYPE i.
" Aktuelles Datumlv_date = sy-datum.
" Tage addieren/subtrahierenlv_date = sy-datum + 30. " 30 Tage späterlv_date = sy-datum - 7. " 7 Tage früher
" Differenz zwischen Datenlv_days = sy-datum - '20240101'.WRITE: / 'Tage seit Jahresanfang:', lv_days.
" Datum zerlegenDATA: 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).
" Datum zusammensetzenlv_date = |{ lv_year }{ lv_month }{ lv_day }|.2. Monats- und Jahresberechnungen
DATA: lv_date TYPE sy-datum.
" Monate addierenCALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL' EXPORTING date = sy-datum days = 0 months = 3 " 3 Monate signum = '+' years = 0 IMPORTING calc_date = lv_date.
" Jahre addierenCALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL' EXPORTING date = sy-datum days = 0 months = 0 signum = '+' years = 1 " 1 Jahr IMPORTING calc_date = lv_date.
" Monatsanfang ermittelnDATA(lv_month_start) = sy-datum.lv_month_start+6(2) = '01'.
" Monatsende ermittelnCALL FUNCTION 'RP_LAST_DAY_OF_MONTHS' EXPORTING day_in = sy-datum IMPORTING last_day_of_month = lv_date.
" QuartalsanfangDATA(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. Wochentag und Kalenderwoche
DATA: lv_weekday TYPE p, lv_week TYPE scal-week.
" Wochentag (1=Montag, 7=Sonntag)CALL FUNCTION 'DAY_IN_WEEK' EXPORTING datum = sy-datum IMPORTING woession = lv_weekday.
CASE lv_weekday. WHEN 1. WRITE: / 'Montag'. WHEN 2. WRITE: / 'Dienstag'. WHEN 3. WRITE: / 'Mittwoch'. WHEN 4. WRITE: / 'Donnerstag'. WHEN 5. WRITE: / 'Freitag'. WHEN 6. WRITE: / 'Samstag'. WHEN 7. WRITE: / 'Sonntag'.ENDCASE.
" KalenderwocheCALL FUNCTION 'DATE_GET_WEEK' EXPORTING date = sy-datum IMPORTING week = lv_week.
WRITE: / 'Kalenderwoche:', lv_week. " Format: YYYYWW4. Fabrikkalender
DATA: lv_workdays TYPE i, lv_target_date TYPE sy-datum.
" Arbeitstage zwischen zwei DatenCALL FUNCTION 'RKE_SELECT_FACTDAYS_FOR_PERIOD' EXPORTING i_datab = '20240101' i_datbi = '20240131' i_factid = '01' " Fabrikkalender-ID IMPORTING e_factdays = lv_workdays.
WRITE: / 'Arbeitstage im Januar:', lv_workdays.
" Arbeitstage addierenCALL FUNCTION 'BKK_ADD_WORKINGDAY' EXPORTING i_date = sy-datum i_days = 5 " 5 Arbeitstage i_calendar_id = '01' IMPORTING e_date = lv_target_date.
WRITE: / 'In 5 Arbeitstagen:', lv_target_date.
" Prüfen ob ArbeitstagCALL 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: / 'Heute ist ein Arbeitstag'.ELSEIF sy-subrc = 4. WRITE: / 'Heute ist kein Arbeitstag'.ENDIF.5. Feiertage
DATA: lt_holidays TYPE TABLE OF iscal_day.
" Feiertage für ein JahrCALL FUNCTION 'HOLIDAY_GET' EXPORTING holiday_calendar = 'DE' " Feiertagskalender 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.
" Prüfen ob FeiertagCALL 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: / 'Heute ist Feiertag'.ENDIF.6. Timestamps
DATA: lv_timestamp TYPE timestamp, lv_timestampl TYPE timestampl.
" Aktueller TimestampGET TIME STAMP FIELD lv_timestampl.WRITE: / 'Timestamp:', lv_timestampl.
" Timestamp aus Datum/Zeit erstellenCONVERT DATE sy-datum TIME sy-uzeit INTO TIME STAMP lv_timestamp TIME ZONE sy-zonlo.
" Timestamp in Datum/Zeit konvertierenDATA: 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: / 'Datum:', lv_date, 'Zeit:', lv_time.
" Timestamp-DifferenzDATA: lv_ts1 TYPE timestampl, lv_ts2 TYPE timestampl, lv_diff TYPE timestampl.
GET TIME STAMP FIELD lv_ts1." ... Verarbeitung ...GET TIME STAMP FIELD lv_ts2.
lv_diff = lv_ts2 - lv_ts1. " Differenz in SekundenWRITE: / 'Dauer:', lv_diff, 'Sekunden'.7. Zeitzonen
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.
" In UTC konvertierenCONVERT TIME STAMP lv_timestamp TIME ZONE 'UTC' INTO DATE lv_date_utc TIME lv_time_utc.
" In lokale Zeit konvertierenCONVERT 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: / 'Lokal:', lv_date_loc, lv_time_loc.
" Zeitzone aus Werk ermittelnSELECT 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. Datum formatieren
DATA: lv_date TYPE sy-datum VALUE '20241124', lv_formatted TYPE string.
" Mit String Templateslv_formatted = |{ lv_date DATE = USER }|. " Benutzerformatlv_formatted = |{ lv_date DATE = ISO }|. " 2024-11-24lv_formatted = |{ lv_date DATE = ENVIRONMENT }|. " Systemformat
WRITE: / lv_formatted.
" Mit FunktionsbausteinCALL FUNCTION 'CONVERT_DATE_TO_EXTERNAL' EXPORTING date_internal = lv_date IMPORTING date_external = lv_formatted.
" Eigenes Formatlv_formatted = |{ lv_date+6(2) }.{ lv_date+4(2) }.{ lv_date(4) }|." 24.11.20249. Zeit formatieren
DATA: lv_time TYPE sy-uzeit VALUE '143052', lv_formatted TYPE string.
" Mit String Templateslv_formatted = |{ lv_time TIME = USER }|.lv_formatted = |{ lv_time TIME = ISO }|. " 14:30:52
" Eigenes Formatlv_formatted = |{ lv_time(2) }:{ lv_time+2(2) }|. " 14:3010. Datumsvalidierung
DATA: lv_date TYPE sy-datum VALUE '20240230'. " Ungültig: 30. Feb
" Prüfung mit FunktionsbausteinCALL FUNCTION 'DATE_CHECK_PLAUSIBILITY' EXPORTING date = lv_date EXCEPTIONS plausibility_check_failed = 1 OTHERS = 2.
IF sy-subrc <> 0. WRITE: / 'Ungültiges Datum'.ENDIF.
" Einfache PrüfungIF lv_date IS INITIAL OR lv_date = '00000000'. WRITE: / 'Datum ist leer'.ENDIF.
" Bereich prüfenIF lv_date < '19000101' OR lv_date > '99991231'. WRITE: / 'Datum außerhalb gültigem Bereich'.ENDIF.11. Date Helper Klasse
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 'Montag' WHEN 2 THEN 'Dienstag' WHEN 3 THEN 'Mittwoch' WHEN 4 THEN 'Donnerstag' WHEN 5 THEN 'Freitag' WHEN 6 THEN 'Samstag' WHEN 7 THEN 'Sonntag' ). ENDMETHOD.ENDCLASS.
" VerwendungDATA(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: / 'Nächster Monat:', lv_next_month, / 'Monatsende:', lv_month_end, / 'Wochentag:', lv_weekday.12. Zeitdifferenz berechnen
" Sekunden zwischen zwei ZeitpunktenDATA: 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.
" Als Timestamps berechnenDATA: 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: / 'Differenz:', lv_hours, 'Stunden'.13. Performance-Messung
DATA: lv_start TYPE timestampl, lv_end TYPE timestampl, lv_runtime TYPE p DECIMALS 3.
GET TIME STAMP FIELD lv_start.
" Code ausführenLOOP AT lt_data INTO DATA(ls_data). " Verarbeitung...ENDLOOP.
GET TIME STAMP FIELD lv_end.
" Laufzeit in Sekundenlv_runtime = cl_abap_tstmp=>subtract( tstmp1 = lv_end tstmp2 = lv_start).
WRITE: / 'Laufzeit:', lv_runtime, 'Sekunden'.14. SQL Datumsfunktionen
" Modernes Open SQL mit DatumsfunktionenSELECT 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).
" Gruppierung nach MonatSELECT 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. Datum in RAP
" CDS View mit Datumsberechnungen@AbapCatalog.viewEnhancementCategory: [#NONE]define view entity ZI_OrderDates as select from vbak{ key vbeln, erdat,
@Semantics.systemDate.createdAt: true erdat as CreatedAt,
// Berechnete Felder dats_days_between(erdat, $session.system_date) as DaysAgo, dats_add_days(erdat, 30) as DueDate}Wichtige Funktionsbausteine
| Funktionsbaustein | Beschreibung |
|---|---|
RP_CALC_DATE_IN_INTERVAL | Monate/Jahre addieren |
RP_LAST_DAY_OF_MONTHS | Monatsende |
DATE_GET_WEEK | Kalenderwoche |
DAY_IN_WEEK | Wochentag |
HOLIDAY_GET | Feiertage |
DATE_CHECK_WORKINGDAY | Arbeitstag prüfen |
BKK_ADD_WORKINGDAY | Arbeitstage addieren |
Wichtige Hinweise / Best Practice
- sy-datum/sy-uzeit nur für aktuelle Zeit, nicht manipulieren.
- Timestamps für genaue Zeitmessung und Zeitzonen.
- Fabrikkalender für Geschäftslogik mit Arbeitstagen.
- GET TIME STAMP statt sy-uzeit für Präzision.
- UTC für Speicherung, lokale Zeit für Anzeige.
- String Templates für Formatierung:
|{ date DATE = ISO }|. - Datumsfunktionen in SQL ab ABAP 7.50 verfügbar.
- Validation vor Berechnungen durchführen.
- Kombinieren Sie mit Built-in Functions für weitere Operationen.