cancel
Showing results for 
Search instead for 
Did you mean: 

Need ABAP logic - DATE Intervals

Former Member
0 Kudos

Hi,

I have a situation where I have the below date range in a IT and need to get the new date range rows into new IT without considering the overlap rows. I require ABAP logic  for this scenario.

START DATE     ENDDATE

12-01-2012        10-02-2012

11-02-2012        05-02-2012

05-02-2012        01-02-2012

23-01-2012       15-02-2012

23-02-2012       15-04-2012

09-10-2012        13-11-2012

If you see the 2 and 3 records they are subsets and fall within the first record range and so I can ignore these records as the range is covered by the first record. Now the 4th record end date has exceeded the first record end date so I will create a new record like below by deleting the first 4 rows into a new IT and the first 4 records will be represented by single row and the rest of the rows will follow as they are exclusive date intervals

12-01-2012     15-02-2012

23-02-2012      15-04-2012

09-10-2012      13-11-2012

Hope I tried to explain my problem correctly.

Thank You

Praneeth

Accepted Solutions (1)

Accepted Solutions (1)

raymond_giuseppi
Active Contributor
0 Kudos

(I was slower )

TYPES: BEGIN OF date_range,

        low TYPE d,

        high TYPE d,

       END OF date_range.

DATA: itab TYPE TABLE OF date_range,

      new_interval LIKE LINE OF itab,

      etab TYPE RANGE OF d,

      current_interval LIKE LINE OF etab.

DEFINE add_date.

  new_interval-low = &1.

  new_interval-high = &2.

  append new_interval to itab.

END-OF-DEFINITION.

add_date '20120112' '20120210'.

add_date '20120211' '20120205'.

add_date '20120205' '20120201'.

add_date '20120123' '20120215'.

add_date '20120223' '20110415'.

add_date '20121009' '20121113'.

SORT itab BY low high. " sort data

CLEAR current_interval.

LOOP AT itab INTO new_interval.

  IF new_interval-low LE current_interval-high. " new interval low in current interval

    IF new_interval-high GT current_interval-high. " if not included extend interval else ignore

      current_interval-high = new_interval-high.

    ENDIF.

  ELSE. " not in current interval

    IF current_interval IS NOT INITIAL. " save curren if defined

      APPEND current_interval TO etab.

    ENDIF.

    current_interval-sign = 'I'. " open new interval

    current_interval-option = 'BT'.

    current_interval-low = new_interval-low.

    current_interval-high = new_interval-high.

  ENDIF.

ENDLOOP.

IF current_interval IS NOT INITIAL. " save last interval if defined

  APPEND current_interval TO etab.

ENDIF.

giving etab :

I    BT    20120112    20120215

I    BT    20120223    20110415

I    BT    20121009    20121113

Regards,

Raymond

Answers (5)

Answers (5)

Former Member
0 Kudos

just change littel logic & all your interval work...

TYPES: BEGIN OF date_range,

        low TYPE d,

        high TYPE d,

       END OF date_range.

DATA: itab TYPE TABLE OF date_range,

      new_interval LIKE LINE OF itab,

      etab TYPE RANGE OF d,

      current_interval LIKE LINE OF etab.

DEFINE add_date.

if     &1 GE &2

  new_interval-low = &1.

  new_interval-high = &2.

  append new_interval to itab.

ELSE.

  new_interval-low = &2.

  new_interval-high = &1.

  append new_interval to itab.

ELSE.

Endif.

END-OF-DEFINITION.

add_date '20120112' '20120210'.

add_date '20120211' '20120205'.

add_date '20120205' '20120201'.

add_date '20120123' '20120215'.

add_date '20120223' '20110415'.

add_date '20121009' '20121113'.

SORT itab BY low high. " sort data

CLEAR current_interval.

LOOP AT itab INTO new_interval.

  IF new_interval-low LE current_interval-high. " new interval low in current interval

    IF new_interval-high GT current_interval-high. " if not included extend interval else ignore

      current_interval-high = new_interval-high.

    ENDIF.

  ELSE. " not in current interval

    IF current_interval IS NOT INITIAL. " save curren if defined

      APPEND current_interval TO etab.

    ENDIF.

    current_interval-sign = 'I'. " open new interval

    current_interval-option = 'BT'.

    current_interval-low = new_interval-low.

    current_interval-high = new_interval-high.

  ENDIF.

ENDLOOP.

IF current_interval IS NOT INITIAL. " save last interval if defined

  APPEND current_interval TO etab.

ENDIF.

Former Member
0 Kudos

Hi Praneeth,

Ya, Eithan has given correct answer But, You can do another way also.

You can check the all record entries based on range while checking the records is anything has overlapped in between the start date and end date those records will delete and end date also update the entry

Please find the below code. I hope it will helps to u and check the code and execute the program

REPORT  ztest_range_date_intervals.

TYPES: BEGIN OF tp_wa1 .

TYPES: stdate TYPE sydatum ,

             endate TYPE sydatum,

              del_flag TYPE flag.

TYPES: END OF tp_wa1.

DATA: it_wa1 TYPE TABLE OF tp_wa1,

           it_wa2 TYPE TABLE OF tp_wa1,

           it_wa3 TYPE TABLE OF tp_wa1.

DATA: st_wa1 LIKE LINE OF it_wa1.

DATA : w_wa2 TYPE tp_wa1,

            l_endate TYPE datum.

             w_wa1 TYPE tp_wa1,

             l_flag TYPE flag.

FIELD-SYMBOLS :<st_wa1> TYPE tp_wa1,

                             <st_wa2> TYPE tp_wa1.

st_wa1-stdate = '20120112' .

st_wa1-endate = '20120210' .

APPEND st_wa1 TO it_wa1.

st_wa1-stdate = '20120211' .

st_wa1-endate = '20120205' .

APPEND st_wa1 TO it_wa1.

st_wa1-stdate = '20120205' .

st_wa1-endate = '20120201' .

APPEND st_wa1 TO it_wa1.

st_wa1-stdate = '20120123' .

st_wa1-endate = '20120215' .

APPEND st_wa1 TO it_wa1.

st_wa1-stdate = '20120223' .

st_wa1-endate = '20120415' .

APPEND st_wa1 TO it_wa1.

st_wa1-stdate = '20121009' .

st_wa1-endate = '20121113' .

APPEND st_wa1 TO it_wa1.

UNASSIGN <st_wa1>.

LOOP AT it_wa1 ASSIGNING <st_wa1>.

   IF sy-tabix = 1.

     w_wa1 = <st_wa1>.

     APPEND w_wa1 TO it_wa2.

     CLEAR w_wa1.

   ELSE.

     LOOP AT it_wa2 ASSIGNING <st_wa2> WHERE ( ( endate GE <st_wa1>-stdate

                                       AND       stdate LE <st_wa1>-stdate )

                                       AND     ( endate GE <st_wa1>-endate

                                       AND       stdate LE <st_wa1>-endate ) )

                                       OR    ( ( endate GE <st_wa1>-stdate

                                       AND       stdate LE <st_wa1>-stdate )

                                       OR      ( endate GE <st_wa1>-endate

                                       AND       stdate LE <st_wa1>-endate ) ).

       IF <st_wa1>-endate GT <st_wa2>-endate.

         CLEAR l_flag.

         l_flag = 'X'.

       ELSE.

         CLEAR <st_wa1>-endate.

       ENDIF.

       IF l_flag = 'X'.

         CLEAR w_wa1.

         w_wa1 = <st_wa1>.

         APPEND w_wa1 TO it_wa3.

       ENDIF.

       CLEAR l_flag.

       CONTINUE.

     ENDLOOP.

   ENDIF.

ENDLOOP.

DELETE it_wa1 WHERE ( endate IS INITIAL ).

LOOP AT it_wa3 ASSIGNING <st_wa2>.

   LOOP AT it_wa1 ASSIGNING <st_wa1> .

     IF <st_wa1>-endate LT <st_wa2>-endate.

       l_endate = <st_wa2>-endate.

       <st_wa1>-endate = <st_wa2>-endate.

     ELSEIF l_endate = <st_wa1>-endate.

       <st_wa1>-del_flag = 'X'.

     ENDIF.

   ENDLOOP.

ENDLOOP.

DELETE it_wa1 WHERE del_flag = 'X'.

LOOP AT it_wa1 ASSIGNING <st_wa1>.

   WRITE 😕 <st_wa1>-stdate, <st_wa1>-endate.

ENDLOOP.

Thanks

sekhar

Former Member
0 Kudos

Hi Kumar,

Code with exceptions handling.

REPORT  y_provide.

TYPES: BEGIN OF tp_wa1 .
TYPES: stdate TYPE sydatum ,
              endate TYPE sydatum .
TYPES: END OF tp_wa1.
TYPES: tt_wa1 TYPE TABLE OF tp_wa1.

DATA: st_wa1 TYPE LINE OF tt_wa1,
            st_wa2 TYPE LINE OF tt_wa1.

DATA: it_wa1 TYPE tt_wa1.
DATA: flag    TYPE char1 .

PERFORM provd.
*&---------------------------------------------------------------------*
*&      Form  PROVD
*&---------------------------------------------------------------------*
FORM provd .

  DATA: l_tabix   TYPE sy-tabix,
           l_overlap TYPE char1 VALUE 'X'.

  st_wa1-stdate = '20120112' .
  st_wa1-endate = '20120210' .
  APPEND st_wa1 TO it_wa1.


  st_wa1-stdate = '20120205' .
  st_wa1-endate = '20120211' .
  APPEND st_wa1 TO it_wa1.


  st_wa1-stdate = '20120201' .
  st_wa1-endate = '20120205' .
  APPEND st_wa1 TO it_wa1.


  st_wa1-stdate = '20120123' .
  st_wa1-endate = '20120215' .
  APPEND st_wa1 TO it_wa1.


  st_wa1-stdate = '20120223' .
  st_wa1-endate = '20120415' .
  APPEND st_wa1 TO it_wa1.


  st_wa1-stdate = '20121009' .
  st_wa1-endate = '20121113' .
  APPEND st_wa1 TO it_wa1.

  SORT it_wa1 BY stdate .

  WHILE l_overlap IS NOT INITIAL.
    PERFORM provide_run
                     CHANGING
                              it_wa1
                              l_overlap.
  ENDWHILE.

  PROVIDE FIELDS * FROM it_wa1 INTO st_wa1
                                 VALID flag
                                 BOUNDS stdate AND endate
          BETWEEN '20120101' AND '20121231'
          INCLUDING GAPS .

    WRITE: / st_wa1-stdate, st_wa1-endate , flag .

    SKIP.

  ENDPROVIDE.

ENDFORM.                    " PROVD

*&---------------------------------------------------------------------*
*&      Form  PROVIDE_RUN
*&---------------------------------------------------------------------*
FORM provide_run
                  CHANGING
                            pt_wa1    TYPE tt_wa1
                            p_overlap TYPE char1.

  DATA: oref1   TYPE REF TO cx_sy_provide_interval_overlap,
              oref2   TYPE REF TO cx_sy_provide_table_not_sorted.

  DATA: l_tabix TYPE sy-index,
               l_line  TYPE sy-index.

  CLEAR p_overlap.

  TRY .

      PROVIDE FIELDS * FROM pt_wa1 INTO st_wa1
                                     VALID flag
                                     BOUNDS stdate AND endate
              BETWEEN '20120101' AND '20121231'
              INCLUDING GAPS .

      ENDPROVIDE.

    CATCH cx_sy_provide_interval_overlap INTO oref1.
      p_overlap = 'O'.
      l_line = oref1->line.

    CATCH cx_sy_provide_table_not_sorted INTO oref2.
      p_overlap = 'S'.
      l_line = oref2->line.

  ENDTRY.

  READ TABLE pt_wa1 INTO st_wa2 INDEX l_line.

  CHECK sy-subrc EQ 0.
  CASE p_overlap.
    WHEN 'O'.
      IF st_wa2-endate GE st_wa1-endate.
        st_wa1-endate = st_wa2-endate.
      ENDIF.
      APPEND st_wa1 TO pt_wa1.
      l_tabix = l_line - 1.
      DO l_line TIMES.
        DELETE pt_wa1 INDEX l_tabix.
      ENDDO.
    WHEN 'S'.
      DELETE pt_wa1 INDEX l_line.
    WHEN OTHERS.
  ENDCASE.

  SORT pt_wa1 BY stdate .

ENDFORM.                    " PROVIDE_RUN

Best regards

Boris

Former Member
0 Kudos

Hello Boris / Eitan,

I see that the code suggested by you is working very fast for all cases but I see that it is failing for the below case .. can you please verify. I have input as below ..

st_wa1-stdate = '20121102' .

st_wa1-endate = '20121110' .

APPEND st_wa1 TO it_wa1.

st_wa1-stdate = '20121122' .

st_wa1-endate = '20121125' .

APPEND st_wa1 TO it_wa1.

st_wa1-stdate = '20121122' .

st_wa1-endate = '20121127' .

APPEND st_wa1 TO it_wa1.

RESULT :- for range 01.11.2012 to 31.12.2012

01.01.2012 01.11.2012

02.11.2012 10.11.2012 X

11.11.2012 31.12.2012

Actually the end result should have been like below ..

01.01.2012 01.11.2012

02.11.2012 10.11.2012 X

11.11.2012 21.11.2012

22.11.2012 27.11.2012 X

28.11.2012 31.12.2012

I tried debugging but did not get the clue ..

Regards

Praneeth

Former Member
0 Kudos

Hi Praneeth,

Please change statement DO.

Old:   DO l_line TIMES.

New: DO l_tabix TIMES.

Best regards

Boris

Former Member
0 Kudos

Hi Praneeth,

Please change statement DO.

Old:   DO l_line TIMES.

New: DO 2 TIMES.

Best regards

Boris

rosenberg_eitan
Active Contributor
0 Kudos

The rebuilt ranges should be in it_wa3.
it_wa3 will be used as input to the provide command.

  TYPES: BEGIN OF tp_wa1 .
  TYPES: stdate TYPE sydatum ,
         endate TYPE sydatum .
  TYPES: END OF tp_wa1.

  DATA: it_wa1 TYPE TABLE OF tp_wa1 .
  DATA: st_wa1 LIKE LINE OF it_wa1 .

  st_wa1-stdate = '20120112' .
  st_wa1-endate = '20120210' .
  APPEND st_wa1 TO it_wa1.
  st_wa1-stdate = '20120121' .
  st_wa1-endate = '20120220' .
  APPEND st_wa1 TO it_wa1.
  st_wa1-stdate = '20120223' .
  st_wa1-endate = '20120415' .
  APPEND st_wa1 TO it_wa1.
  st_wa1-stdate = '20120122' .
  st_wa1-endate = '20120418' .
  APPEND st_wa1 TO it_wa1.
  st_wa1-stdate = '20120223' .
  st_wa1-endate = '20120415' .
  APPEND st_wa1 TO it_wa1.
  st_wa1-stdate = '20121009' .
  st_wa1-endate = '20121113' .
  APPEND st_wa1 TO it_wa1.

  TYPES: BEGIN OF tp_wa2 .

  TYPES: date TYPE sydatum ,
         cntr TYPE i .
  TYPES: END OF tp_wa2.

  DATA: it_wa2 TYPE TABLE OF tp_wa2 .
  DATA: st_wa2 LIKE LINE OF it_wa2 .

  DATA: date_count TYPE i .

  LOOP AT it_wa1 INTO st_wa1  .

    date_count = ( st_wa1-endate - st_wa1-stdate ) + 1 .

    st_wa2-date = st_wa1-stdate .
    st_wa2-cntr = 1 .

    DO date_count TIMES.
      COLLECT st_wa2 INTO it_wa2 .
      ADD 1 TO st_wa2-date .
    ENDDO.

  ENDLOOP.

  SORT it_wa2 BY date .

  DATA: it_wa3 TYPE TABLE OF tp_wa1 .
  DATA: st_wa3 LIKE LINE OF it_wa3 .
  DATA: date   TYPE sydatum .
  DATA: dif    TYPE i .

  LOOP AT it_wa2 INTO st_wa2 .

    IF st_wa3-stdate IS INITIAL .
      st_wa3-stdate = st_wa2-date .
    ENDIF .

    IF st_wa3-endate IS INITIAL .
      st_wa3-endate = st_wa2-date .
    ENDIF .

    dif = st_wa2-date - st_wa3-endate .

    IF dif LE 1 .
      st_wa3-endate = st_wa2-date .
    ENDIF .

    IF dif GT 1 .
      APPEND st_wa3 TO it_wa3 .
      CLEAR st_wa3 .
      st_wa3-stdate = st_wa2-date .
      st_wa3-endate = st_wa2-date .
    ENDIF .

  ENDLOOP .

* Left over ?
  IF st_wa3 IS NOT INITIAL .
    APPEND st_wa3 TO it_wa3 .
  ENDIF .

Former Member
0 Kudos

Hi Eitan,

I have to agree that it was a mind boggling piece of code and it took me some time to understand the logic. Now I will use the PROVIDE statement after this code to get the gap intervals and I thank you for this code and I am sure you would have spent some time to write this code. I have marked this answer as correct.

Thank you again.

Regards

Praneeth

rosenberg_eitan
Active Contributor
0 Kudos
Former Member
0 Kudos

Yes, Perfect.

I wanted the same result to proceed further in my code.

Thanks Again !

rosenberg_eitan
Active Contributor
0 Kudos

Just add to the end.

  DATA: flag TYPE abap_bool .



  PROVIDE FIELDS * FROM it_wa3 INTO st_wa3

                                 VALID flag

                                 BOUNDS stdate AND endate

          BETWEEN '20120101' AND '20121231'

          INCLUDING GAPS .



    WRITE: / st_wa3-stdate, st_wa3-endate , flag .



    SKIP.



  ENDPROVIDE.

Former Member
0 Kudos

HI Again,

Any idea on how to handle exceptions on PROVIDE command ..I see two exceptions associated with this syntax and not sure how to handle them in the code. As I am using this command in the user exit do not want to see the program dump if there is an exception.

CX_SY_PROVIDE_INTERVAL_OVERLAP

CX_SY_PROVIDE_TABLE_NOT_SORTED

Regards

Praneeth

rosenberg_eitan
Active Contributor
0 Kudos

Have a look at "TRY"

Transaction code       ABAPHELP

search for try...

Former Member
0 Kudos

Hi Eitan,

I used the above code and started running it in Production but I see performance issues if the end date range is set to 31.12.9999 and the code is taking time to complete as it is running the loop until 31.12.9999 to find other intervals if they exist and can we make changes to the code to make it faster.

Regards

Praneeth

rosenberg_eitan
Active Contributor
0 Kudos

Have a look at the code of Boris Lishinskyi.

I think that this code might be better for you since he is not
inflating the date ranges.

Regards.

Former Member
0 Kudos

hello,

you need to run through the IT for each entry. Take for example first entry and then loop at the IT and

see if there is another entry near this range, you need to check the start and end dates in this case.

If the end date matches then check start date if the start date is less than current change it to the less than date. If start date is same and end date is greater than current change to the greater end date. You need to mark the entry you compared as used or deleted. The current date with new start and end dates need to move to another IT. Smae logic applies to all entries. Hope you understand this. If there is another scenarios you need to code accordingly. This is just the start.

best regards,

swanand

Former Member
0 Kudos

hello,

please open a single thread for your queries. It seems you have opened two threads for the same issue or requirement you have. Close one of them and use only one.

best regards

swanand

Former Member
0 Kudos

Hi,

The other thread is now closed .

Please advise.

Regards

Praneeth.