diff --git a/src/zcl_excel_common.clas.abap b/src/zcl_excel_common.clas.abap index 26d9924..67a9e6c 100644 --- a/src/zcl_excel_common.clas.abap +++ b/src/zcl_excel_common.clas.abap @@ -102,9 +102,22 @@ CLASS zcl_excel_common DEFINITION VALUE(ev_unescaped_string) TYPE string RAISING zcx_excel . + "!
Convert date from Excel format to SAP
+ "! @parameter ip_value | String being an Excel number representing a date (e.g. 45141 means 2023/08/03, + "! 45141.58832 means 2023/08/03 14:07:11). Important: if the input is date + + "! time, use the additional parameter IP_EXACT = 'X'. + "! @parameter ip_exact | If the input value also contains the time i.e. a fractional part exists + "! (e.g. 45141.58832 means 2023/08/03 14:07:11), ip_exact = 'X' will + "! return the exact date (e.g. 2023/08/03), while ip_exact = ' ' (default) will + "! return the rounded-up date (e.g. 2023/08/04). NB: this rounding-up doesn't + "! happen if the time is before 12:00:00. + "! @parameter ep_value | Date corresponding to the input Excel number. It returns a null date if + "! the input value contains non-numeric characters. + "! @raising zcx_excel | The numeric input corresponds to a date before 1900/1/1 or after 9999/12/31. CLASS-METHODS excel_string_to_date IMPORTING !ip_value TYPE zexcel_cell_value + !ip_exact TYPE abap_bool DEFAULT abap_false RETURNING VALUE(ep_value) TYPE d RAISING @@ -860,11 +873,16 @@ CLASS zcl_excel_common IMPLEMENTATION. METHOD excel_string_to_date. DATA: lv_date_int TYPE i. + DATA lv_error_text TYPE string. CHECK ip_value IS NOT INITIAL AND ip_value CN ' 0'. TRY. - lv_date_int = floor( ip_value ). + IF ip_exact = abap_false. + lv_date_int = ip_value. + ELSE. + lv_date_int = trunc( ip_value ). + ENDIF. IF lv_date_int NOT BETWEEN 1 AND 2958465. zcx_excel=>raise_text( 'Unable to interpret date' ). ENDIF. @@ -876,7 +894,8 @@ CLASS zcl_excel_common IMPLEMENTATION. ep_value = ep_value + 1. ENDIF. CATCH cx_sy_conversion_error. - zcx_excel=>raise_text( 'Index out of bounds' ). + lv_error_text = |String "{ ip_value }" is not a valid Excel date|. + zcx_excel=>raise_text( lv_error_text ). ENDTRY. ENDMETHOD. @@ -898,7 +917,7 @@ CLASS zcl_excel_common IMPLEMENTATION. TRY. - lv_day_fraction = ip_value - floor( ip_value ). + lv_day_fraction = frac( ip_value ). lv_seconds_in_day = lv_day_fraction * lc_seconds_in_day. ep_value = lv_seconds_in_day. diff --git a/src/zcl_excel_common.clas.testclasses.abap b/src/zcl_excel_common.clas.testclasses.abap index b0703ed..bf5f471 100644 --- a/src/zcl_excel_common.clas.testclasses.abap +++ b/src/zcl_excel_common.clas.testclasses.abap @@ -1,8 +1,5 @@ CLASS lcl_excel_common_test DEFINITION DEFERRED. -CLASS lcl_string_to_date_and_time DEFINITION DEFERRED. -CLASS zcl_excel_common DEFINITION - LOCAL FRIENDS lcl_excel_common_test - lcl_string_to_date_and_time. +CLASS zcl_excel_common DEFINITION LOCAL FRIENDS lcl_excel_common_test. *----------------------------------------------------------------------* * CLASS lcl_Excel_Common_Test DEFINITION @@ -58,6 +55,7 @@ CLASS lcl_excel_common_test DEFINITION FOR TESTING METHODS excel_string_to_time3 FOR TESTING RAISING cx_static_check. METHODS excel_string_to_time4 FOR TESTING RAISING cx_static_check. METHODS excel_string_to_time5 FOR TESTING RAISING cx_static_check. + METHODS excel_string_to_time6 FOR TESTING RAISING cx_static_check. METHODS time_to_excel_string1 FOR TESTING RAISING cx_static_check. METHODS time_to_excel_string2 FOR TESTING RAISING cx_static_check. METHODS time_to_excel_string3 FOR TESTING RAISING cx_static_check. @@ -691,6 +689,45 @@ CLASS lcl_excel_common_test IMPLEMENTATION. level = if_aunit_constants=>fatal ). ENDTRY. + +* 45141.58832 (2023/08/03 14:07:11) ip_exact = abap_false -> 2023/08/04 + TRY. + ep_value = zcl_excel_common=>excel_string_to_date( ip_value = '45141.58832' + ip_exact = abap_false ). + cl_abap_unit_assert=>assert_equals( + act = ep_value + exp = '20230804' ). + CATCH zcx_excel INTO lx_excel. + cl_abap_unit_assert=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* 45141.58832 (2023/08/03 14:07:11) ip_exact = abap_true -> 2023/08/03 + TRY. + ep_value = zcl_excel_common=>excel_string_to_date( ip_value = '45141.58832' + ip_exact = abap_true ). + cl_abap_unit_assert=>assert_equals( + act = ep_value + exp = '20230803' ). + CATCH zcx_excel INTO lx_excel. + cl_abap_unit_assert=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. + +* 45141.48832 (2023/08/03 11:43:11) ip_exact = abap_false -> 2023/08/03 + TRY. + ep_value = zcl_excel_common=>excel_string_to_date( ip_value = '45141.48832' + ip_exact = abap_false ). + cl_abap_unit_assert=>assert_equals( + act = ep_value + exp = '20230803' ). + CATCH zcx_excel INTO lx_excel. + cl_abap_unit_assert=>fail( + msg = 'unexpected exception' + level = if_aunit_constants=>critical ). + ENDTRY. ENDMETHOD. "excel_String_To_Date @@ -770,6 +807,21 @@ CLASS lcl_excel_common_test IMPLEMENTATION. ENDTRY. ENDMETHOD. + METHOD excel_string_to_time6. + DATA ep_value TYPE t. +* 45141.58832 (2023/08/03 14:07:11) -> 14:07:11 + TRY. + ep_value = zcl_excel_common=>excel_string_to_time( ip_value = '45141.58832' ). + + cl_abap_unit_assert=>assert_equals( + act = ep_value + exp = '140711' ). + + CATCH zcx_excel INTO lx_excel. + cl_abap_unit_assert=>fail( lx_excel->get_text( ) ). + ENDTRY. + ENDMETHOD. + METHOD time_to_excel_string1. DATA ep_value TYPE zexcel_cell_value. @@ -1760,115 +1812,3 @@ CLASS lcl_excel_common_test IMPLEMENTATION. ENDMETHOD. ENDCLASS. - - - -CLASS lcl_string_to_date_and_time DEFINITION FINAL FOR TESTING - DURATION SHORT - RISK LEVEL HARMLESS. - - PRIVATE SECTION. - CONSTANTS date_20230803 TYPE d VALUE '20230803'. - CONSTANTS dbs1900_initial TYPE d VALUE '18991230'. "Serial date 0 in (default) 1900 date base system - CONSTANTS dbs1900bc_initial TYPE d VALUE '18991231'. "Serial date 0 in 1900 backwards compatibility date base system - CONSTANTS dbs1904bc_initial TYPE d VALUE '19040101'. "Serial date 0 in 1904 backwards compatibility date base system - CONSTANTS time_140711 TYPE t VALUE '140711'. - CONSTANTS time_initial TYPE t VALUE '000000'. - CONSTANTS dbs1900_20230803_000000 TYPE string VALUE `45141.000000000000`. "Serial date 2023-08-03 time zero - CONSTANTS dbs1900_00000000_140711 TYPE string VALUE `0.588321759256`. "Serial date zero time 14:07:11 - CONSTANTS dbs1900_20230803_140711 TYPE string VALUE `45141.588321759256`. "Serial date 2023-08-03 time 14:07:11 - - DATA cut TYPE REF TO zcl_excel_common. - DATA excel_error TYPE REF TO zcx_excel. - - METHODS: - setup, - teardown. - - METHODS: - date_to_date FOR TESTING RAISING cx_static_check, - time_to_time FOR TESTING RAISING cx_static_check, - datetime_to_date FOR TESTING RAISING cx_static_check, - datetime_to_time FOR TESTING RAISING cx_static_check, - date_to_time FOR TESTING RAISING cx_static_check, - time_to_date FOR TESTING RAISING cx_static_check. - ENDCLASS. - - - -CLASS lcl_string_to_date_and_time IMPLEMENTATION. - - METHOD setup. - CREATE OBJECT cut. - ENDMETHOD. - - METHOD teardown. - CLEAR cut. - CLEAR excel_error. - ENDMETHOD. - - METHOD date_to_date. - TRY. - cl_abap_unit_assert=>assert_equals( - act = cut->excel_string_to_date( dbs1900_20230803_000000 ) - exp = date_20230803 ). - CATCH zcx_excel INTO excel_error. - cl_abap_unit_assert=>fail( excel_error->get_text( ) ). - ENDTRY. - ENDMETHOD. - - METHOD time_to_time. - TRY. - cl_abap_unit_assert=>assert_equals( - act = cut->excel_string_to_time( dbs1900_00000000_140711 ) - exp = time_140711 ). - CATCH zcx_excel INTO excel_error. - cl_abap_unit_assert=>fail( excel_error->get_text( ) ). - ENDTRY. - ENDMETHOD. - - METHOD datetime_to_date. - TRY. - cl_abap_unit_assert=>assert_equals( - act = cut->excel_string_to_date( dbs1900_20230803_140711 ) - exp = date_20230803 ). - CATCH zcx_excel INTO excel_error. - cl_abap_unit_assert=>fail( excel_error->get_text( ) ). - ENDTRY. - ENDMETHOD. - - METHOD datetime_to_time. - TRY. - cl_abap_unit_assert=>assert_equals( - act = cut->excel_string_to_time( dbs1900_20230803_140711 ) - exp = time_140711 ). - CATCH zcx_excel INTO excel_error. - cl_abap_unit_assert=>fail( excel_error->get_text( ) ). - ENDTRY. - ENDMETHOD. - - METHOD date_to_time. - TRY. - cl_abap_unit_assert=>assert_equals( - act = cut->excel_string_to_time( dbs1900_20230803_000000 ) - exp = time_initial ). - CATCH zcx_excel INTO excel_error. - cl_abap_unit_assert=>fail( excel_error->get_text( ) ). - ENDTRY. - ENDMETHOD. - - METHOD time_to_date. - TRY. - cl_abap_unit_assert=>assert_equals( - act = cut->excel_string_to_date( dbs1900_00000000_140711 ) - exp = dbs1900_initial ). - cl_abap_unit_assert=>fail( 'Until dates before 1900-01-01 are supported, an exception is expected' ). - CATCH zcx_excel INTO excel_error. -* cl_abap_unit_assert=>fail( excel_error->get_text( ) ). - cl_abap_unit_assert=>assert_equals( - act = excel_error->get_text( ) - exp = 'Unable to interpret date' ). - ENDTRY. - ENDMETHOD. - -ENDCLASS. diff --git a/src/zcl_excel_common.clas.xml b/src/zcl_excel_common.clas.xml index a372874..a648e43 100644 --- a/src/zcl_excel_common.clas.xml +++ b/src/zcl_excel_common.clas.xml @@ -120,6 +120,11 @@