使用日期、时间和时戳计算

学习目标

  • 使用日期、时间和时间戳计算。

含日期、时间和时戳的计算

内置 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 在线观看。

试用 - 含时间、日期和时戳的计算

  1. 创建实施接口 IF_OO_ADT_CLASSRUN 的新类。

  2. 将以下代码复制到 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 }| ).
  1. 按 Ctrl + F3 激活类。

  2. 在代码周围播放以熟悉主题。

使用时戳执行计算

在本练习中,您将航班持续时间添加到乘客航班的 ABAP 类的控制台输出。根据出发时间和到达时间计算乘客航班的持续时间,同时考虑出发机场和目的地机场的不同时区。

模板:

  • /LRN/CL_S4D401_TCS_TYPE_CONV(全局类)

解决方案:

  • /LRN/CL_S4D401_TCS_TIMESTAMP(全局类)

任务 1: 复制模板(可选)

复制模板类 /LRN/CL_S4D401_TCS_TYPE_CONV。如果已完成上一练习,则可以跳过此任务并继续编辑类 ZCL_##_SOLUTION

步骤

  1. 将类 /LRN/CL_S4D401_TCS_TYPE_CONV 复制到您自己的包中的类(建议名称:ZCL_##_SOLUTION,其中 ## 代表组编号)。

  2. 在项目浏览器中,右键单击类 /LRN/CL_S4D401_TCS_TYPE_CONV 以打开上下文菜单。

  3. 从上下文菜单中,选择复制....

  4. 在包字段中输入的名称。在名称字段中,输入 ZCL_##_SOLUTION,其中 ## 代表组编号。

  5. 选择下一步

  6. 确认传输请求并选择完成

  7. 激活复制。

  8. Ctrl + F3 激活类。

任务 2: 扩展输出

编辑本地类 LCL_PASSENGER_FLIGHT,并使用航班持续时间的组件**持续时间**(分钟)扩展属性 connection_details。然后编辑 GET_DESCRIPTION 方法并将航班持续时间添加到输出。

步骤

  1. 在局部类 LCL_PASSENGER_FLIGHT 中,使用整数类型的组件**持续时间**扩展属性 connection_details

  2. 在局部类 LCL_PASSENGER_FLIGHT 中,找到结构类型 st_connection_details 的定义。

  3. 如下调整代码:

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.
  1. 导航到方法 GET_DESCRIPTION 的实施。在方法的末尾,插入一个 APPEND 语句,该语句将 connection_details-duration 和合适的说明添加到 r_result

  2. 添加以下代码:

APPEND |Duration:       { connection_details-duration } minutes| TO r_result.
  1. 激活 ABAP 类。

  2. Ctrl + F3

任务 3: 计算乘客航班的持续时间

class_constructor 方法中,计算乘客航班的持续时间。使用启运时间和运达时间,并考虑机场位于不同的时区。

提示

您可以在数据库表 /LRN/AIRPORT 中找到机场的时区。

步骤

  1. 向类似表的属性 connections_buffer 添加列**持续时间**。

  2. 找到结构类型 st_connections_buffer 的定义。

  3. 如下调整代码:

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.
  1. 扩展 CLASS_CONSTRUCTOR 方法的实现。方法开始时,将所有机场的机场标识和时区从数据库表 /LRN/AIRPORT 读取到本地内部表**"机场**"。

  2. 如下调整代码:

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.
  1. 在 方法的末尾,使用内联声明的工作区域(建议名称:connection)对 connections_buffer 属性添加循环。

  2. 如下调整代码:

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.
  1. 使用 ABAP 语句 CONVERT…INTO UTCLONG 将以本地时间表示的启运时间转换为通用时戳。使用启运机场的时区作为时区,并使用当前系统日期作为日期。

警告

CONVERT ...INTO UTCLONG 语句采用日期、时间和时区,并将这些值转换为 UTC 时间戳。在本练习中,我们将当前系统日期用作启运和到达的参考日期。这意味着我们假设转机不跨越日期变更线。这是对练习场景进行的简化。对于跨日期行的连接,计算会导致持续时间值不正确。提示 调用方法 cl_abap_context_info=>get_system_date 以检索当前系统日期。

  1. 如下调整代码:

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.
  1. 对到达时间和到达机场执行相同的操作。

  2. 如下调整代码:

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.
  1. 使用两个 UTC 时戳的差值填充工作区**连接的组件持续时间**(分钟)。

注意

使用内置函数 utclong_diff 计算差值。请记住, 函数以秒为单位返回差值。

  1. 如下调整代码:

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.
  1. 最后,使用循环内的 MODIFY 语句,用工作区中组件**持续时间**的新内容更新内部表 connections_buffer 的当前行。

  2. 如下调整代码:

connection-duration = utclong_diff(
high = arrival_utclong
low  = departure_utclong
) / 60.
MODIFY connections_buffer FROM connection TRANSPORTING duration.
  1. 激活代码并将其测试为控制台应用。

  2. Ctrl + F3

  3. F9