Date & Time Operations en ABAP incluyen calculos de fechas, calendarios de fabrica, timestamps y conversion de zonas horarias. Las clases modernas como CL_ABAP_DATFM complementan los modulos de funciones clasicos.
Tipos de datos
| Tipo | Formato | Ejemplo |
|---|---|---|
| D (DATS) | YYYYMMDD | 20241124 |
| T (TIMS) | HHMMSS | 143052 |
| TIMESTAMPL | YYYYMMDDHHMMSS.sssssss | 20241124143052.1234567 |
| TIMESTAMP | YYYYMMDDHHMMSS | 20241124143052 |
Ejemplos
1. Calculos basicos de fechas
DATA: lv_date TYPE sy-datum, lv_days TYPE i.
" Fecha actuallv_date = sy-datum.
" Sumar/restar diaslv_date = sy-datum + 30. " 30 dias despueslv_date = sy-datum - 7. " 7 dias antes
" Diferencia entre fechaslv_days = sy-datum - '20240101'.WRITE: / 'Dias desde inicio de ano:', lv_days.
" Descomponer fechaDATA: 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).
" Componer fechalv_date = |{ lv_year }{ lv_month }{ lv_day }|.2. Calculos de meses y anos
DATA: lv_date TYPE sy-datum.
" Sumar mesesCALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL' EXPORTING date = sy-datum days = 0 months = 3 " 3 meses signum = '+' years = 0 IMPORTING calc_date = lv_date.
" Sumar anosCALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL' EXPORTING date = sy-datum days = 0 months = 0 signum = '+' years = 1 " 1 ano IMPORTING calc_date = lv_date.
" Obtener inicio de mesDATA(lv_month_start) = sy-datum.lv_month_start+6(2) = '01'.
" Obtener fin de mesCALL FUNCTION 'RP_LAST_DAY_OF_MONTHS' EXPORTING day_in = sy-datum IMPORTING last_day_of_month = lv_date.
" Inicio de 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. Dia de la semana y semana calendario
DATA: lv_weekday TYPE p, lv_week TYPE scal-week.
" Dia de la semana (1=Lunes, 7=Domingo)CALL FUNCTION 'DAY_IN_WEEK' EXPORTING datum = sy-datum IMPORTING woession = lv_weekday.
CASE lv_weekday. WHEN 1. WRITE: / 'Lunes'. WHEN 2. WRITE: / 'Martes'. WHEN 3. WRITE: / 'Miercoles'. WHEN 4. WRITE: / 'Jueves'. WHEN 5. WRITE: / 'Viernes'. WHEN 6. WRITE: / 'Sabado'. WHEN 7. WRITE: / 'Domingo'.ENDCASE.
" Semana calendarioCALL FUNCTION 'DATE_GET_WEEK' EXPORTING date = sy-datum IMPORTING week = lv_week.
WRITE: / 'Semana calendario:', lv_week. " Formato: YYYYWW4. Calendario de fabrica
DATA: lv_workdays TYPE i, lv_target_date TYPE sy-datum.
" Dias laborables entre dos fechasCALL FUNCTION 'RKE_SELECT_FACTDAYS_FOR_PERIOD' EXPORTING i_datab = '20240101' i_datbi = '20240131' i_factid = '01' " ID de calendario de fabrica IMPORTING e_factdays = lv_workdays.
WRITE: / 'Dias laborables en enero:', lv_workdays.
" Sumar dias laborablesCALL FUNCTION 'BKK_ADD_WORKINGDAY' EXPORTING i_date = sy-datum i_days = 5 " 5 dias laborables i_calendar_id = '01' IMPORTING e_date = lv_target_date.
WRITE: / 'En 5 dias laborables:', lv_target_date.
" Verificar si es dia laborableCALL 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: / 'Hoy es dia laborable'.ELSEIF sy-subrc = 4. WRITE: / 'Hoy no es dia laborable'.ENDIF.5. Dias festivos
DATA: lt_holidays TYPE TABLE OF iscal_day.
" Dias festivos para un anoCALL FUNCTION 'HOLIDAY_GET' EXPORTING holiday_calendar = 'DE' " Calendario de festivos 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.
" Verificar si es dia festivoCALL 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: / 'Hoy es dia festivo'.ENDIF.6. Timestamps
DATA: lv_timestamp TYPE timestamp, lv_timestampl TYPE timestampl.
" Timestamp actualGET TIME STAMP FIELD lv_timestampl.WRITE: / 'Timestamp:', lv_timestampl.
" Crear timestamp desde fecha/horaCONVERT DATE sy-datum TIME sy-uzeit INTO TIME STAMP lv_timestamp TIME ZONE sy-zonlo.
" Convertir timestamp a fecha/horaDATA: 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: / 'Fecha:', lv_date, 'Hora:', lv_time.
" Diferencia de timestampsDATA: lv_ts1 TYPE timestampl, lv_ts2 TYPE timestampl, lv_diff TYPE timestampl.
GET TIME STAMP FIELD lv_ts1." ... Procesamiento ...GET TIME STAMP FIELD lv_ts2.
lv_diff = lv_ts2 - lv_ts1. " Diferencia en segundosWRITE: / 'Duracion:', lv_diff, 'Segundos'.7. Zonas horarias
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 a UTCCONVERT TIME STAMP lv_timestamp TIME ZONE 'UTC' INTO DATE lv_date_utc TIME lv_time_utc.
" Convertir a hora localCONVERT 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.
" Obtener zona horaria de plantaSELECT 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. Formatear fecha
DATA: lv_date TYPE sy-datum VALUE '20241124', lv_formatted TYPE string.
" Con String Templateslv_formatted = |{ lv_date DATE = USER }|. " Formato usuariolv_formatted = |{ lv_date DATE = ISO }|. " 2024-11-24lv_formatted = |{ lv_date DATE = ENVIRONMENT }|. " Formato sistema
WRITE: / lv_formatted.
" Con modulo de funcionesCALL FUNCTION 'CONVERT_DATE_TO_EXTERNAL' EXPORTING date_internal = lv_date IMPORTING date_external = lv_formatted.
" Formato propiolv_formatted = |{ lv_date+6(2) }.{ lv_date+4(2) }.{ lv_date(4) }|." 24.11.20249. Formatear hora
DATA: lv_time TYPE sy-uzeit VALUE '143052', lv_formatted TYPE string.
" Con String Templateslv_formatted = |{ lv_time TIME = USER }|.lv_formatted = |{ lv_time TIME = ISO }|. " 14:30:52
" Formato propiolv_formatted = |{ lv_time(2) }:{ lv_time+2(2) }|. " 14:3010. Validacion de fecha
DATA: lv_date TYPE sy-datum VALUE '20240230'. " Invalido: 30 de Feb
" Verificacion con modulo de funcionesCALL FUNCTION 'DATE_CHECK_PLAUSIBILITY' EXPORTING date = lv_date EXCEPTIONS plausibility_check_failed = 1 OTHERS = 2.
IF sy-subrc <> 0. WRITE: / 'Fecha invalida'.ENDIF.
" Verificacion simpleIF lv_date IS INITIAL OR lv_date = '00000000'. WRITE: / 'Fecha esta vacia'.ENDIF.
" Verificar rangoIF lv_date < '19000101' OR lv_date > '99991231'. WRITE: / 'Fecha fuera del rango valido'.ENDIF.11. Clase auxiliar de fechas
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 'Lunes' WHEN 2 THEN 'Martes' WHEN 3 THEN 'Miercoles' WHEN 4 THEN 'Jueves' WHEN 5 THEN 'Viernes' WHEN 6 THEN 'Sabado' WHEN 7 THEN 'Domingo' ). ENDMETHOD.ENDCLASS.
" UsoDATA(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: / 'Proximo mes:', lv_next_month, / 'Fin de mes:', lv_month_end, / 'Dia de la semana:', lv_weekday.12. Calcular diferencia de tiempo
" Segundos entre dos momentosDATA: 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.
" Calcular como 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: / 'Diferencia:', lv_hours, 'Horas'.13. Medicion de rendimiento
DATA: lv_start TYPE timestampl, lv_end TYPE timestampl, lv_runtime TYPE p DECIMALS 3.
GET TIME STAMP FIELD lv_start.
" Ejecutar codigoLOOP AT lt_data INTO DATA(ls_data). " Procesamiento...ENDLOOP.
GET TIME STAMP FIELD lv_end.
" Tiempo de ejecucion en segundoslv_runtime = cl_abap_tstmp=>subtract( tstmp1 = lv_end tstmp2 = lv_start).
WRITE: / 'Tiempo de ejecucion:', lv_runtime, 'Segundos'.14. Funciones de fecha SQL
" Open SQL moderno con funciones de fechaSELECT 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).
" Agrupacion por mesSELECT 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. Fecha en RAP
" CDS View con calculos de fecha@AbapCatalog.viewEnhancementCategory: [#NONE]define view entity ZI_OrderDates as select from vbak{ key vbeln, erdat,
@Semantics.systemDate.createdAt: true erdat as CreatedAt,
// Campos calculados dats_days_between(erdat, $session.system_date) as DaysAgo, dats_add_days(erdat, 30) as DueDate}Modulos de funciones importantes
| Modulo de funciones | Descripcion |
|---|---|
RP_CALC_DATE_IN_INTERVAL | Sumar meses/anos |
RP_LAST_DAY_OF_MONTHS | Fin de mes |
DATE_GET_WEEK | Semana calendario |
DAY_IN_WEEK | Dia de la semana |
HOLIDAY_GET | Dias festivos |
DATE_CHECK_WORKINGDAY | Verificar dia laborable |
BKK_ADD_WORKINGDAY | Sumar dias laborables |
Notas importantes / Mejores practicas
- sy-datum/sy-uzeit solo para hora actual, no manipular.
- Timestamps para medicion de tiempo precisa y zonas horarias.
- Calendario de fabrica para logica de negocio con dias laborables.
- GET TIME STAMP en lugar de sy-uzeit para precision.
- UTC para almacenamiento, hora local para visualizacion.
- String Templates para formateo:
|{ date DATE = ISO }|. - Funciones de fecha en SQL disponibles desde ABAP 7.50.
- Validacion realizar antes de calculos.
- Combina con Built-in Functions para mas operaciones.