on 10-15-2012 3:34 PM
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
(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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
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 .
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
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
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
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
94 | |
11 | |
11 | |
6 | |
6 | |
4 | |
3 | |
3 | |
3 | |
3 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.