Les operations Date & Time en ABAP comprennent les calculs de dates, le calendrier d’usine, les Timestamps et la conversion de fuseaux horaires. Les classes modernes comme CL_ABAP_DATFM completent les modules fonctionnels classiques.
Types de donnees
| Type | Format | Exemple |
|---|---|---|
| D (DATS) | AAAAMMJJ | 20241124 |
| T (TIMS) | HHMMSS | 143052 |
| TIMESTAMPL | AAAAMMJJHHMMSS.sssssss | 20241124143052.1234567 |
| TIMESTAMP | AAAAMMJJHHMMSS | 20241124143052 |
Exemples
1. Calculs de dates de base
DATA: lv_date TYPE sy-datum, lv_days TYPE i.
" Date actuellelv_date = sy-datum.
" Ajouter/soustraire des jourslv_date = sy-datum + 30. " 30 jours plus tardlv_date = sy-datum - 7. " 7 jours plus tot
" Difference entre dateslv_days = sy-datum - '20240101'.WRITE: / 'Jours depuis le debut de l annee:', lv_days.
" Decomposer la 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).
" Composer la datelv_date = |{ lv_year }{ lv_month }{ lv_day }|.2. Calculs de mois et d’annees
DATA: lv_date TYPE sy-datum.
" Ajouter des moisCALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL" EXPORTING date = sy-datum days = 0 months = 3 " 3 mois signum = '+" years = 0 IMPORTING calc_date = lv_date.
" Ajouter des anneesCALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL" EXPORTING date = sy-datum days = 0 months = 0 signum = '+" years = 1 " 1 an IMPORTING calc_date = lv_date.
" Determiner le debut du moisDATA(lv_month_start) = sy-datum.lv_month_start+6(2) = '01'.
" Determiner la fin du moisCALL FUNCTION 'RP_LAST_DAY_OF_MONTHS" EXPORTING day_in = sy-datum IMPORTING last_day_of_month = lv_date.
" Debut du trimestreDATA(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. Jour de la semaine et semaine calendaire
DATA: lv_weekday TYPE p, lv_week TYPE scal-week.
" Jour de la semaine (1=lundi, 7=dimanche)CALL FUNCTION 'DAY_IN_WEEK" EXPORTING datum = sy-datum IMPORTING woession = lv_weekday.
CASE lv_weekday. WHEN 1. WRITE: / 'Lundi'. WHEN 2. WRITE: / 'Mardi'. WHEN 3. WRITE: / 'Mercredi'. WHEN 4. WRITE: / 'Jeudi'. WHEN 5. WRITE: / 'Vendredi'. WHEN 6. WRITE: / 'Samedi'. WHEN 7. WRITE: / 'Dimanche'.ENDCASE.
" Semaine calendaireCALL FUNCTION 'DATE_GET_WEEK" EXPORTING date = sy-datum IMPORTING week = lv_week.
WRITE: / 'Semaine calendaire:', lv_week. " Format : AAAASS4. Calendrier d’usine
DATA: lv_workdays TYPE i, lv_target_date TYPE sy-datum.
" Jours ouvres entre deux datesCALL FUNCTION 'RKE_SELECT_FACTDAYS_FOR_PERIOD" EXPORTING i_datab = '20240101" i_datbi = '20240131" i_factid = '01' " ID du calendrier d'usine IMPORTING e_factdays = lv_workdays.
WRITE: / 'Jours ouvres en janvier:', lv_workdays.
" Ajouter des jours ouvresCALL FUNCTION 'BKK_ADD_WORKINGDAY" EXPORTING i_date = sy-datum i_days = 5 " 5 jours ouvres i_calendar_id = '01" IMPORTING e_date = lv_target_date.
WRITE: / 'Dans 5 jours ouvres:', lv_target_date.
" Verifier si c'est un jour ouvreCALL 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: / 'Aujourd hui est un jour ouvre'.ELSEIF sy-subrc = 4. WRITE: / 'Aujourd hui n est pas un jour ouvre'.ENDIF.5. Jours feries
DATA: lt_holidays TYPE TABLE OF iscal_day.
" Jours feries pour une anneeCALL FUNCTION 'HOLIDAY_GET" EXPORTING holiday_calendar = 'FR' " Calendrier des jours feries 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.
" Verifier si c'est un jour ferieCALL FUNCTION 'HOLIDAY_CHECK_AND_GET_INFO" EXPORTING date = sy-datum holiday_calendar_id = 'FR" IMPORTING holiday_found = DATA(lv_is_holiday) EXCEPTIONS OTHERS = 1.
IF lv_is_holiday = abap_true. WRITE: / 'Aujourd hui est un jour ferie'.ENDIF.6. Timestamps
DATA: lv_timestamp TYPE timestamp, lv_timestampl TYPE timestampl.
" Timestamp actuelGET TIME STAMP FIELD lv_timestampl.WRITE: / 'Timestamp:', lv_timestampl.
" Creer un Timestamp a partir de date/heureCONVERT DATE sy-datum TIME sy-uzeit INTO TIME STAMP lv_timestamp TIME ZONE sy-zonlo.
" Convertir un Timestamp en date/heureDATA: 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, 'Heure:', lv_time.
" Difference de TimestampsDATA: lv_ts1 TYPE timestampl, lv_ts2 TYPE timestampl, lv_diff TYPE timestampl.
GET TIME STAMP FIELD lv_ts1." ... Traitement ...GET TIME STAMP FIELD lv_ts2.
lv_diff = lv_ts2 - lv_ts1. " Difference en secondesWRITE: / 'Duree:', lv_diff, 'secondes'.7. Fuseaux horaires
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.
" Convertir en UTCCONVERT TIME STAMP lv_timestamp TIME ZONE 'UTC" INTO DATE lv_date_utc TIME lv_time_utc.
" Convertir en heure localeCONVERT 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.
" Determiner le fuseau horaire a partir d'une usineSELECT 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. Formater une date
DATA: lv_date TYPE sy-datum VALUE '20241124', lv_formatted TYPE string.
" Avec les String Templateslv_formatted = |{ lv_date DATE = USER }|. " Format utilisateurlv_formatted = |{ lv_date DATE = ISO }|. " 2024-11-24lv_formatted = |{ lv_date DATE = ENVIRONMENT }|. " Format systeme
WRITE: / lv_formatted.
" Avec un module fonctionnelCALL FUNCTION 'CONVERT_DATE_TO_EXTERNAL" EXPORTING date_internal = lv_date IMPORTING date_external = lv_formatted.
" Format personnaliselv_formatted = |{ lv_date+6(2) }.{ lv_date+4(2) }.{ lv_date(4) }|." 24.11.20249. Formater une heure
DATA: lv_time TYPE sy-uzeit VALUE '143052', lv_formatted TYPE string.
" Avec les String Templateslv_formatted = |{ lv_time TIME = USER }|.lv_formatted = |{ lv_time TIME = ISO }|. " 14:30:52
" Format personnaliselv_formatted = |{ lv_time(2) }:{ lv_time+2(2) }|. " 14:3010. Validation de date
DATA: lv_date TYPE sy-datum VALUE '20240230'. " Invalide : 30 fevrier
" Verification avec module fonctionnelCALL FUNCTION 'DATE_CHECK_PLAUSIBILITY" EXPORTING date = lv_date EXCEPTIONS plausibility_check_failed = 1 OTHERS = 2.
IF sy-subrc <> 0. WRITE: / 'Date invalide'.ENDIF.
" Verification simpleIF lv_date IS INITIAL OR lv_date = '00000000'. WRITE: / 'La date est vide'.ENDIF.
" Verifier la plageIF lv_date < '19000101' OR lv_date > '99991231'. WRITE: / 'Date en dehors de la plage valide'.ENDIF.11. Classe d’aide pour les dates
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 'Lundi" WHEN 2 THEN 'Mardi" WHEN 3 THEN 'Mercredi" WHEN 4 THEN 'Jeudi" WHEN 5 THEN 'Vendredi" WHEN 6 THEN 'Samedi" WHEN 7 THEN 'Dimanche" ). ENDMETHOD.ENDCLASS.
" UtilisationDATA(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: / 'Mois prochain:', lv_next_month, / 'Fin du mois:', lv_month_end, / 'Jour de la semaine:', lv_weekday.12. Calculer la difference de temps
" Secondes entre deux momentsDATA: 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.
" Calculer comme 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, 'heures'.13. Mesure de performance
DATA: lv_start TYPE timestampl, lv_end TYPE timestampl, lv_runtime TYPE p DECIMALS 3.
GET TIME STAMP FIELD lv_start.
" Executer le codeLOOP AT lt_data INTO DATA(ls_data). " Traitement...ENDLOOP.
GET TIME STAMP FIELD lv_end.
" Duree en secondeslv_runtime = cl_abap_tstmp=>subtract( tstmp1 = lv_end tstmp2 = lv_start).
WRITE: / 'Duree:', lv_runtime, 'secondes'.14. Fonctions de date SQL
" Open SQL moderne avec fonctions de dateSELECT 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).
" Regroupement par moisSELECT 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 dans RAP
" CDS View avec calculs de date@AbapCatalog.viewEnhancementCategory: [#NONE]define view entity ZI_OrderDates as select from vbak{ key vbeln, erdat,
@Semantics.systemDate.createdAt: true erdat as CreatedAt,
// Champs calcules dats_days_between(erdat, $session.system_date) as DaysAgo, dats_add_days(erdat, 30) as DueDate}Modules fonctionnels importants
| Module fonctionnel | Description |
|---|---|
RP_CALC_DATE_IN_INTERVAL | Ajouter des mois/annees |
RP_LAST_DAY_OF_MONTHS | Fin du mois |
DATE_GET_WEEK | Semaine calendaire |
DAY_IN_WEEK | Jour de la semaine |
HOLIDAY_GET | Jours feries |
DATE_CHECK_WORKINGDAY | Verifier jour ouvre |
BKK_ADD_WORKINGDAY | Ajouter des jours ouvres |
Remarques importantes / Bonnes pratiques
- sy-datum/sy-uzeit uniquement pour l’heure actuelle, ne pas modifier.
- Timestamps pour la mesure precise du temps et les fuseaux horaires.
- Calendrier d’usine pour la logique metier avec les jours ouvres.
- GET TIME STAMP au lieu de sy-uzeit pour la precision.
- UTC pour le stockage, heure locale pour l’affichage.
- String Templates pour le formatage :
|{ date DATE = ISO }|. - Fonctions de date en SQL disponibles depuis ABAP 7.50.
- Validation avant les calculs.
- Combinez avec les Built-in Functions pour d’autres operations.