使用日期、时间和时戳计算
学习目标
使用日期、时间和时间戳计算。
含日期、时间和时戳的计算

内置 ABAP 类型 D 和 T 允许您分别表示一天和时间。无论用户的输出格式如何,日期的格式始终为 YYYYMMDD。无论用户的输出格式如何,时间始终采用 24 小时制记法格式 HHMMSS。时间精确到 1 秒。
时间和日期的系统信息
类 cl_abap_context_info 提供可用于查找当前时间和日期信息的方法。
观看以下视频,了解更多信息。
视频:本节含 SAP 官方视频(视频 ID
1_umsoamm4),需在 learning.sap.com 在线观看。
日期和时间计算

在 ABAP 中,您可以执行直接日期计算,例如查找两个日期之间的差异,或从给定日期加上和减去天数。要执行计算,ABAP 将日期转换为整数(自 0001 年 1 月 1 日起的天数)并添加或减去相关值。执行时间计算时,ABAP 将时间转换为自午夜起的秒数。
使用含日期字段的偏移量和长度

ABAP 以 YYYYMMDD 格式存储日期。您可以使用偏移量和长度访问日期的各个组件。例如,要访问月份,您需要日期字段的第五个字符和第六个字符。您可以通过指定 var_date+4(2) 来执行此操作,这指示系统将四个字符放入日期,然后获取接下来的两个字符。然后,对年、月和日的访问如下所示:
年:var_date(4)
月:var_date+4(2)
天:var_date +6(2)
使用时戳字段
除类型 D 外,ABAP 还具有内置数据类型 utclong,它表示符合 ISO-8601 的时戳。此数据类型的精确度为 100 纳秒,并遵循格式 YYYY-MM-DD HH:MM:SS.ssssssss。
观看以下视频,详细了解如何使用时戳字段。
视频:本节含 SAP 官方视频(视频 ID
1_o60gj9o8),需在 learning.sap.com 在线观看。
试用 - 含时间、日期和时戳的计算
创建实施接口 IF_OO_ADT_CLASSRUN 的新类。
将以下代码复制到 METHOD if_oo_adt_classrun~main. 和 ENDMETHOD. 语句之间的编辑器中:
DATA timestamp1 TYPE utclong.
DATA timestamp2 TYPE utclong.
DATA difference TYPE decfloat34.
DATA date_user TYPE d.
DATA time_user TYPE t.
timestamp1 = utclong_current( ).
out->write( |Current UTC time { timestamp1 }| ).
timestamp2 = utclong_add( val = timestamp1 days = 7 ).
out->write( |Added 7 days to current UTC time { timestamp2 }| ).
difference = utclong_diff( high = timestamp2 low = timestamp1 ).
out->write( |Difference between timestamps in seconds: { difference }| ).
out->write( |Difference between timestamps in days: { difference / 3600 / 24 }| ).
CONVERT UTCLONG utclong_current( )
INTO DATE date_user
TIME time_user
TIME ZONE cl_abap_context_info=>get_user_time_zone( ).
out->write( |UTC timestamp split into date (type D) and time (type T )| ).
out->write( |according to the user's time zone (cl_abap_context_info=>get_user_time_zone( ) ).| ).
out->write( |{ date_user date = user }, { time_user time = user }| ).
按 Ctrl + F3 激活类。
在代码周围播放以熟悉主题。
使用时戳执行计算
在本练习中,您将航班持续时间添加到乘客航班的 ABAP 类的控制台输出。根据出发时间和到达时间计算乘客航班的持续时间,同时考虑出发机场和目的地机场的不同时区。
模板:
/LRN/CL_S4D401_TCS_TYPE_CONV(全局类)
解决方案:
/LRN/CL_S4D401_TCS_TIMESTAMP(全局类)
任务 1: 复制模板(可选)
复制模板类 /LRN/CL_S4D401_TCS_TYPE_CONV。如果已完成上一练习,则可以跳过此任务并继续编辑类 ZCL_##_SOLUTION。
步骤
将类
/LRN/CL_S4D401_TCS_TYPE_CONV复制到您自己的包中的类(建议名称:ZCL_##_SOLUTION,其中 ## 代表组编号)。在项目浏览器中,右键单击类
/LRN/CL_S4D401_TCS_TYPE_CONV以打开上下文菜单。从上下文菜单中,选择复制....
在包字段中输入包的名称。在名称字段中,输入
ZCL_##_SOLUTION,其中 ## 代表组编号。选择下一步。
确认传输请求并选择完成。
激活复制。
按
Ctrl + F3激活类。
任务 2: 扩展输出
编辑本地类 LCL_PASSENGER_FLIGHT,并使用航班持续时间的组件**持续时间**(分钟)扩展属性 connection_details。然后编辑 GET_DESCRIPTION 方法并将航班持续时间添加到输出。
步骤
在局部类
LCL_PASSENGER_FLIGHT中,使用整数类型的组件**持续时间**扩展属性connection_details。在局部类
LCL_PASSENGER_FLIGHT中,找到结构类型st_connection_details的定义。如下调整代码:
TYPES:
BEGIN OF st_connection_details,
airport_from_id TYPE /dmo/airport_from_id,
airport_to_id TYPE /dmo/airport_to_id,
departure_time TYPE /dmo/flight_departure_time,
arrival_time TYPE /dmo/flight_arrival_time,
duration TYPE i,
END OF st_connection_details.
导航到方法
GET_DESCRIPTION的实施。在方法的末尾,插入一个 APPEND 语句,该语句将connection_details-duration和合适的说明添加到r_result。添加以下代码:
APPEND |Duration: { connection_details-duration } minutes| TO r_result.
激活 ABAP 类。
按
Ctrl + F3。
任务 3: 计算乘客航班的持续时间
在 class_constructor 方法中,计算乘客航班的持续时间。使用启运时间和运达时间,并考虑机场位于不同的时区。
提示
您可以在数据库表 /LRN/AIRPORT 中找到机场的时区。
步骤
向类似表的属性
connections_buffer添加列**持续时间**。找到结构类型
st_connections_buffer的定义。如下调整代码:
TYPES:
BEGIN OF st_connections_buffer,
carrier_id TYPE /dmo/carrier_id,
connection_id TYPE /dmo/connection_id,
airport_from_id TYPE /dmo/airport_from_id,
airport_to_id TYPE /dmo/airport_to_id,
departure_time TYPE /dmo/flight_departure_time,
arrival_time TYPE /dmo/flight_arrival_time,
duration TYPE i,
END OF st_connections_buffer.
扩展
CLASS_CONSTRUCTOR方法的实现。方法开始时,将所有机场的机场标识和时区从数据库表/LRN/AIRPORT读取到本地内部表**"机场**"。如下调整代码:
METHOD class_constructor.
SELECT
FROM /lrn/airport
FIELDS airport_id, timzone
INTO TABLE @DATA(airports).
SELECT
FROM /lrn/connection
FIELDS carrier_id, connection_id,
airport_from_id, airport_to_id, departure_time, arrival_time
INTO TABLE @connections_buffer.
ENDMETHOD.
在 方法的末尾,使用内联声明的工作区域(建议名称:
connection)对connections_buffer属性添加循环。如下调整代码:
METHOD class_constructor.
SELECT
FROM /lrn/airport
FIELDS airport_id, timzone
INTO TABLE @DATA(airports).
SELECT
FROM /lrn/connection
FIELDS carrier_id, connection_id,
airport_from_id, airport_to_id, departure_time, arrival_time
INTO TABLE @connections_buffer.
LOOP AT connections_buffer INTO DATA(connection).
ENDLOOP.
ENDMETHOD.
使用 ABAP 语句 CONVERT…INTO UTCLONG 将以本地时间表示的启运时间转换为通用时戳。使用启运机场的时区作为时区,并使用当前系统日期作为日期。
警告
CONVERT ...INTO UTCLONG 语句采用日期、时间和时区,并将这些值转换为 UTC 时间戳。在本练习中,我们将当前系统日期用作启运和到达的参考日期。这意味着我们假设转机不跨越日期变更线。这是对练习场景进行的简化。对于跨日期行的连接,计算会导致持续时间值不正确。提示 调用方法 cl_abap_context_info=>get_system_date 以检索当前系统日期。
如下调整代码:
DATA(today) = cl_abap_context_info=>get_system_date( ).
LOOP AT connections_buffer INTO DATA(connection).
CONVERT DATE today
TIME connection-departure_time
TIME ZONE airports[ airport_id = connection-airport_from_id ]-timzone
INTO UTCLONG DATA(departure_utclong).
ENDLOOP.
对到达时间和到达机场执行相同的操作。
如下调整代码:
DATA(today) = cl_abap_context_info=>get_system_date( ).
LOOP AT connections_buffer INTO DATA(connection).
CONVERT DATE today
TIME connection-departure_time
TIME ZONE airports[ airport_id = connection-airport_from_id ]-timzone
INTO UTCLONG DATA(departure_utclong).
CONVERT DATE today
TIME connection-arrival_time
TIME ZONE airports[ airport_id = connection-airport_to_id ]-timzone
INTO UTCLONG DATA(arrival_utclong).
ENDLOOP.
使用两个 UTC 时戳的差值填充工作区**
连接的组件持续时间**(分钟)。
注意
使用内置函数 utclong_diff 计算差值。请记住, 函数以秒为单位返回差值。
如下调整代码:
LOOP AT connections_buffer INTO DATA(connection).
CONVERT DATE today
TIME connection-departure_time
TIME ZONE airports[ airport_id = connection-airport_from_id ]-timzone
INTO UTCLONG DATA(departure_utclong).
CONVERT DATE today
TIME connection-arrival_time
TIME ZONE airports[ airport_id = connection-airport_to_id ]-timzone
INTO UTCLONG DATA(arrival_utclong).
connection-duration = utclong_diff(
high = arrival_utclong
low = departure_utclong
) / 60.
ENDLOOP.
最后,使用循环内的
MODIFY语句,用工作区中组件**持续时间**的新内容更新内部表connections_buffer的当前行。如下调整代码:
connection-duration = utclong_diff(
high = arrival_utclong
low = departure_utclong
) / 60.
MODIFY connections_buffer FROM connection TRANSPORTING duration.
激活代码并将其测试为控制台应用。
按
Ctrl + F3。按
F9。