ABAP - XCO System Fields
Is there an alternative for SY or SYST in the XCO Library in ABAP Cloud? It's definitely worth a look.
Table of contents
The XCO classes are helper classes that provide various everyday functions bundled under a public API. You can find more information and an overview of the XCO libraries on the overview page.
Introduction
In this article we look at the library in the area of system fields and what information is already available and what we get for free from the standard. We use the XCO_CP=>SY for this purpose, this object contains all the important information and objects.
User
The user ID is read via the USER. Currently, the interface only has one attribute NAME and thus has the same scope as SY-UNAME.
" Classic
DATA(user_id) = sy-uname.
" XCO
user_id = xco_cp=>sy->user( )->name.
Language
If you want to get the current language of the logged in user, you can use the LANGUAGE object. Here you can get the classic SAP language (D = German, E = English) via VALUE.
" Classic
DATA(language_sap) = sy-langu.
" XCO
language_sap = xco_cp=>sy->language( )->value.
Additionally, further information is available, such as a short text, the description and the identifier in ISO format. This saves reading from the standard Core Data Services.
DATA(short_name) = xco_cp=>sy->language( )->get_name( ).
DATA(long_name) = xco_cp=>sy->language( )->get_long_text_description( ).
DATA(language_iso) = xco_cp=>sy->language( )->as( xco_cp_language=>format->iso_639 ).
Here the information is output to the console so that you can check the results.
Message
In many scenarios, a message output is transferred to the message variables of the SY structure. You can then call these up via the various fields to access all the information.
" Classic
DATA(message_id) = sy-msgid.
DATA(message_number) = sy-msgno.
DATA(message_type) = sy-msgty.
DATA(message_v1) = sy-msgv1.
However, collecting the information is always development-intensive, mapping the individual pieces of information or writing reusable functions. The information is collected via the MESSAGE object and made available as an object. We can use the object to access VALUE, which is a structure of the SYMSG type.
" XCO
DATA(xco_message) = xco_cp=>sy->message( ).
message_id = xco_message->value-msgid.
message_number = xco_message->value-msgno.
message_type = xco_message->value-msgty.
message_v1 = xco_message->value-msgv1.
We will look at the Message object and how to handle it in a separate article.
Date
The DATE object supports a few more functions, so we'll split this section into several parts to look at different parts of the object.
Reading
Simply reading the current date is not that easy. Once we have access to the DATE object, we need to define the format for the output. Unfortunately, there is no default parameter here, but we need to pass a formatter first.
" Classic
DATA(system_date) = sy-datlo.
" XCO
system_date = xco_cp=>sy->date( )->as( xco_cp_time=>format->abap )->value.
Format
Using the AS method, we can specify additional formatters to obtain different outputs. You can find additional filters in the example here.
DATA(iso_8601_basic) = xco_cp=>sy->date( )->as( xco_cp_time=>format->iso_8601_basic )->value.
DATA(iso_8601_extended) = xco_cp=>sy->date( )->as( xco_cp_time=>format->iso_8601_extended )->value.
Let's look at the contents of the objects in the debugger, otherwise the console would change the data type. The different formats can be used for the output, as the result is returned as a string (object).
Components
If you only want to read a component of the date, the information is available via the YEAR, MONTH and DAY attributes.
DATA(date_year) = xco_cp=>sy->date( )->year.
DATA(date_month) = xco_cp=>sy->date( )->month.
DATA(date_day) = xco_cp=>sy->date( )->day.
Calculation
You will also find some methods in the object for calculating with the date. The following methods are available for this:
- ADD - Add to the current date
- SUBTRACT - Subtract from the current date
- OVERWRITE - Overwrite individual components
The methods take the year, month or day, depending on what you want to calculate with or which field you want to overwrite.
DATA(last_week) = xco_cp=>sy->date( )->subtract( iv_day = 7 )->as( xco_cp_time=>format->abap )->value.
DATA(year_2000) = xco_cp=>sy->date( )->overwrite( iv_year = 2000 )->as( xco_cp_time=>format->abap )->value.
In the example above, we take the current date and subtract 7 days (one week) from the date. In the second example, we set the year back to 2000. As usual with XCO, you can combine the calls.
Time
If we take a closer look at the time or the TIME object, then there are almost all the functions here as with the date. How do you determine the current time and output it? Here is a small example:
" Classic
DATA(system_time) = sy-timlo.
" XCO
system_time = xco_cp=>sy->time( )->as( xco_cp_time=>format->abap )->value.
Hint: For further details, see the Date chapter for the relevant functions for the time. However, you can access the hour, minute and second in the components here.
Moment
The MOMENT object is a combination of date and time and can be combined to form a timestamp. The object manages both pieces of information and these can be combined and calculated accordingly.
Creation
How do we actually create a MOMENT object? Basically like the other objects so far. However, there is one point we have not yet looked at: in the standard there is user time and UTC time. If you generate the object, you will always get an object in user time. Here is an example of how you can create the different objects in ABAP.
DATA(moment_user) = xco_cp=>sy->moment( xco_cp_time=>time_zone->user ).
DATA(moment_utc) = xco_cp=>sy->moment( xco_cp_time=>time_zone->utc ).
Formatting
Here we have the same formatters as for date and time. Let's perform the output of the three common formats.
DATA(output_format_abap) = moment_user->as( xco_cp_time=>format->abap )->value.
DATA(output_format_basic) = moment_user->as( xco_cp_time=>format->iso_8601_basic )->value.
DATA(output_format_extended) = moment_user->as( xco_cp_time=>format->iso_8601_extended )->value.
We then look at the result in the debugger to check the types and formatting.
Calculation
The ADD, SUBTRACT and OVERWRITE methods are also available for calculation and can be used to adapt the object. All information from the date to the time can be passed here.
Objects
Different objects can also be generated from a MOMENT object, for example a timestamp, a date or a time. DATE and TIME are attributes on the object that contain the information. For the timestamp there is the method GET_UNIX_TIMESTAMP, which returns a corresponding object.
Comparison
You can compare two moments with each other; there are numerous methods available on the object for this purpose. Here is a short list of the methods and their function:
- IS_BEFORE - Checks whether the object is before the passed moment.
- IS_AFTER - Checks whether the object is after the passed moment.
- IS_NOT_BEFORE and IS_NOT_AFTER - Checks the opposite of the other two methods
To do this, we create the following example and compare a moment in the future (plus one day) with our user's current moment. If everything is correct, the sentence is output to the console.
DATA(future) = xco_cp=>sy->moment( )->add( iv_day = 1 ).
IF moment_user->is_before( future ).
out->write( `The future is not here ...` ).
ENDIF.
Intervals
With the methods INTERVAL_FROM and INTERVAL_TO you get an interval object and you can use the method CONTAINS to check whether another moment lies between the two moments. In the following example we create an interval between now and tomorrow and check whether the UTC time lies between them.
DATA(from_moment_to_future) = moment_user->interval_to( future ).
out->write( from_moment_to_future->contains( moment_utc ) ).
Summary
So let's take another look at which fields we can replace from the SYST today. In addition to the various fields, you also have a number of additional functions at your disposal to prepare, calculate or convert the information.
- SY-UNAME
- SY-DATUM, SY-DATLO
- SY-UZEIT, SY-TIMLO
- SY-LANGU
- SY-MSGID, SY-MSGNO, SY-MSGTY, SY-MSGV1, SY-MSGV2, SY-MSGV3, SY-MSGV4
- TIMESTAMP
Complete example
You can find the complete example in our GitHub repository, where you can also find the other examples from the XCO library. You can find all the latest changes in this commit. Here is the executable class from this article.
CLASS zcl_bs_demo_xco_syst DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PRIVATE SECTION.
METHODS user_name
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS language
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS date
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS time
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS system_message
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS moment
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
ENDCLASS.
CLASS zcl_bs_demo_xco_syst IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
user_name( out ).
language( out ).
date( out ).
time( out ).
system_message( out ).
moment( out ).
ENDMETHOD.
METHOD user_name.
" Classic
DATA(user_id) = sy-uname.
out->write( user_id ).
" XCO
user_id = xco_cp=>sy->user( )->name.
out->write( user_id ).
ENDMETHOD.
METHOD language.
" Classic
DATA(language_sap) = sy-langu.
out->write( language_sap ).
" XCO
language_sap = xco_cp=>sy->language( )->value.
out->write( language_sap ).
DATA(short_name) = xco_cp=>sy->language( )->get_name( ).
out->write( short_name ).
DATA(long_name) = xco_cp=>sy->language( )->get_long_text_description( ).
out->write( long_name ).
DATA(language_iso) = xco_cp=>sy->language( )->as( xco_cp_language=>format->iso_639 ).
out->write( language_iso ).
ENDMETHOD.
METHOD date.
" Classic
DATA(system_date) = sy-datlo.
out->write( system_date ).
" XCO
system_date = xco_cp=>sy->date( )->as( xco_cp_time=>format->abap )->value.
out->write( system_date ).
DATA(iso_8601_basic) = xco_cp=>sy->date( )->as( xco_cp_time=>format->iso_8601_basic )->value.
out->write( iso_8601_basic ).
DATA(iso_8601_extended) = xco_cp=>sy->date( )->as( xco_cp_time=>format->iso_8601_extended )->value.
out->write( iso_8601_extended ).
DATA(date_year) = xco_cp=>sy->date( )->year.
DATA(date_month) = xco_cp=>sy->date( )->month.
DATA(date_day) = xco_cp=>sy->date( )->day.
out->write( date_year ).
out->write( date_month ).
out->write( date_day ).
DATA(last_week) = xco_cp=>sy->date( )->subtract( iv_day = 7 )->as( xco_cp_time=>format->abap )->value.
out->write( last_week ).
DATA(year_2000) = xco_cp=>sy->date( )->overwrite( iv_year = 2000 )->as( xco_cp_time=>format->abap )->value.
out->write( year_2000 ).
ENDMETHOD.
METHOD time.
" Classic
DATA(system_time) = sy-timlo.
out->write( system_time ).
" XCO
system_time = xco_cp=>sy->time( )->as( xco_cp_time=>format->abap )->value.
out->write( system_time ).
ENDMETHOD.
METHOD system_message.
MESSAGE w001(zbs_demo_xco) WITH 'Method' 'Message' INTO DATA(dummy_message).
" Classic
DATA(message_id) = sy-msgid.
DATA(message_number) = sy-msgno.
DATA(message_type) = sy-msgty.
DATA(message_v1) = sy-msgv1.
out->write( message_id ).
out->write( message_number ).
out->write( message_type ).
out->write( message_v1 ).
" XCO
DATA(xco_message) = xco_cp=>sy->message( ).
message_id = xco_message->value-msgid.
message_number = xco_message->value-msgno.
message_type = xco_message->value-msgty.
message_v1 = xco_message->value-msgv1.
out->write( message_id ).
out->write( message_number ).
out->write( message_type ).
out->write( message_v1 ).
ENDMETHOD.
METHOD moment.
DATA(moment_user) = xco_cp=>sy->moment( xco_cp_time=>time_zone->user ).
DATA(moment_utc) = xco_cp=>sy->moment( xco_cp_time=>time_zone->utc ).
DATA(output_format_abap) = moment_user->as( xco_cp_time=>format->abap )->value.
DATA(output_format_basic) = moment_user->as( xco_cp_time=>format->iso_8601_basic )->value.
DATA(output_format_extended) = moment_user->as( xco_cp_time=>format->iso_8601_extended )->value.
out->write( output_format_abap ).
out->write( output_format_basic ).
out->write( output_format_extended ).
DATA(future) = xco_cp=>sy->moment( )->add( iv_day = 1 ).
IF moment_user->is_before( future ).
out->write( `The future is not here ...` ).
ENDIF.
DATA(from_moment_to_future) = moment_user->interval_to( future ).
out->write( from_moment_to_future->contains( moment_utc ) ).
ENDMETHOD.
ENDCLASS.
Conclusion
For some system fields there is already an alternative that can be used today. In some areas the class already offers added value when it comes to preparing the information and should be used in your next project.