接上篇:SAP中的时区和时间戳(上)
上篇介绍了时区、夏令时等基本原理,以及SAP对日期、时间、时间戳的处理逻辑,本篇从技术层面,介绍一下SAP底层ABAP如何处理时间相关字段。
时间定义 -> 获取 -> 转换 -> 存储 -> 显示
一、时间戳的定义
ABAP中时间戳有两种格式:短时间戳、长时间戳
短格式:YYYYMMDDhhmmss,示例数据元素:TIMESTAMP,其域Domain如下
顺便再说一下,在其他开发语言中,更为熟悉的是Unix时间戳,是一个长整型,用来表示1970.01.01 00:00:00(UTC+0)以来的秒数
例如:
二、获取
* 获取时间戳GET TIME STAMP FIELD tsl. "UTC+0时间戳,例如 2024.10.24 00:00:00
* 获取日期、时间,两个字段GET TIME.write: / sy-datum, " 系统时区(UTC-5)日期,例如 2024.10.23/ sy-uzeit, " 系统时区(UTC-5)时间,例如 19:00:00/ sy-datlo, " 用户时区(UTC+8)日期,例如 2024.10.24/ sy-timlo, " 用户时区(UTC+8)时间,例如 08:00:00/ sy-zonlo. " 用户SU3时区,例如 UTC+8
三、转换
1. 时间戳+目标时区-> 目标时区的日期+时间+夏令时情况
DATA: time_stamp TYPE timestamp,tz TYPE ttzz-tzone.tz = 'CST'.time_stamp = 20251024000000.CONVERT TIME STAMP time_stamp TIME ZONE tzINTO DATE DATA(dat) TIME DATA(tim)DAYLIGHT SAVING TIME DATA(dst).cl_demo_output=>write( |{ dat DATE = ISO } {tim TIME = ISO } { dst }| ).time_stamp = 20251124000000.CONVERT TIME STAMP time_stamp TIME ZONE tzINTO DATE dat TIME timDAYLIGHT SAVING TIME dst.cl_demo_output=>write( |{ dat DATE = ISO } {tim TIME = ISO } { dst }| ).cl_demo_output=>display( ).
执行结果
2. 日期+时间+时区->时间戳
CONVERT DATE dat TIME tim DAYLIGHT SAVING TIME 'X'INTO TIME STAMP DATA(time_stamp) TIME ZONE tz.
3. ABAP时间戳<->Unix时间戳
cl_pco_utility=>convert_abap_timestamp_to_java...
四、存储
按照定义,时间戳、日期、时间字段在系统中都是按照数字存储的,仅长格式时间戳带有小数点。
五、显示
1. 日期、时间显示
SAP系统SU3提供了各个国家的常用日期格式,用户可以自行设定,常见如下。
同样可以设定常用时间显示格式以及当地时区:
2. 时间戳显示
SAP格式:时间戳字段一般会有三种不同的展示方式,取决于Domain是否有alpha转换:
1. 原格式:数字
2. 日期、时间格式:UTC时间
3. 日期、时间格式:转换时区,用户当地时间
示例如下(注意比较“值”和“未转换的值”)
对应的域,示例如下
|
|
|
|
|
|
TZNTSTMPS |
TZNTSTMPL |
|
|
SWF_FLEX_TIMESTAMP |
TIME_STAMP_PS |
|
|
|
WRF_REF_UTC_TIMESTAMP_LONG |
除了以上常用的SAP格式,时间戳还有ISO标准(8601):UTC 时间加后缀Z(如 2024-05-20T14:30:00Z),本地时区用 “± 时:分” 表示(如 2024-05-20T14:30:00+08:00),转换类如下:
CALL METHOD cl_gdt_conversion=>date_time_outbound...
五、特殊场景(题外话)
1. 夏令时切换时SAP系统如何处理
参考:7417 - Conversion between standard time and daylight saving time
-
关机2小时或者1小时 -
系统时钟在这两个小时里,运行的慢一点,虽然是2个小时,但是系统时间只走了一个小时
2. 格里高利历的“10天断层”
1582年,罗马教皇格列高利十三世推行新历法(格里高利历,即现行公历),为修正旧儒略历的误差,将当年10月4日的次日直接定为10月15日,跳过了10天(10月5日-14日)。如果你手机上有这个月的日历,应该如下:

SAP中也考虑了这个问题:
d1 = '15821004'.d2 = d1 + 1. " 下一天为1015cl_demo_output=>write( d2 ).days = d2 - d1.cl_demo_output=>write( days ).cl_demo_output=>display( ).

