SAP 的日期與時間 SY-DATUM & SY-UZEIT 是分開,並不像 Oracle datetime 可以直接加減運算,因此可透過轉換成 Timestamp (UTC) 變成秒後,再針對要增加 or 減少的時間轉換成秒後進行運算,最後再把 Timestamp 轉為 Date Time
第一種方法:
透過 RKE_TIMESTAMP_CONVERT_INPUT 把時間轉換成 UTC Timestamp,再透過 RKE_TIMESTAMP_CONVERT_OUTPUT 轉回 DATE/TIME.
CALL FUNCTION 'RKE_TIMESTAMP_CONVERT_INPUT'
CALL FUNCTION 'RKE_TIMESTAMP_CONVERT_OUTPUT'
Sample Code:
report Z_EX_CALC_DATE_TIME.
DATA: L_TIMESTMP LIKE CEST1-TIMESTMP.
DATA : L_DATUM LIKE SY-DATUM,
L_UZEIT LIKE SY-UZEIT.
L_DATUM = SY-DATUM.
L_UZEIT = SY-UZEIT.
WRITE: '現在時間 - ', L_DATUM, L_UZEIT.
CALL FUNCTION 'RKE_TIMESTAMP_CONVERT_INPUT'
EXPORTING
I_DATE = SY-DATUM
I_DAYST = ' '
I_TIME = SY-UZEIT
I_TZONE = SY-TZONE "目前的時區,與 OUTPUT 需相同
IMPORTING
E_TIMESTMP = L_TIMESTMP
EXCEPTIONS
* DATE_INVALID = 1
OTHERS = 2.
IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE 'I' NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.
"加 30 分鐘 * 10000 (Timestamp 後面有四個 0)
L_TIMESTMP = L_TIMESTMP + ( 30 * 60 * 10000 ).
WRITE :/.
CALL FUNCTION 'RKE_TIMESTAMP_CONVERT_OUTPUT'
EXPORTING
I_DAYST = ' '
I_TIMESTMP = L_TIMESTMP
I_TZONE = SY-TZONE "目前的時區,與 INPUT 需相同
IMPORTING
E_DATE = L_DATUM
E_TIME = L_UZEIT.
WRITE: '加30分鐘 - ', L_DATUM, L_UZEIT.
是土法煉鋼 : 針對日期的計算可以透過 Unix epoch time 19700101 00:00:00 UTC 為基準,把目前的時間扣掉 19700101 00:00:00 轉換成秒後,再透過秒的加減再把秒轉換成 Date Time
SAMPLE CODE:
REPORT Z_CALC_DATE_TIME.
DATA: L_DATE LIKE SY-DATUM,
L_TIME(10) TYPE C.
DATA: L_PARA TYPE P.
L_PARA = 30 * 60. "增加 30 分鐘
WRITE:/ '目前時間:', SY-DATUM, SY-UZEIT.
PERFORM CALC_DATE_TIME USING SY-DATUM SY-UZEIT L_PARA
CHANGING L_DATE L_TIME.
WRITE:/ '加 30 分鐘時間:', L_DATE, L_TIME.
FORM CALC_DATE_TIME USING P_WRITEDATE
P_WRITETIME
P_SECOND
CHANGING C_WRITEDATE
C_WRITETIME.
DATA: L_DATE TYPE SY-DATUM,
L_DATE2 TYPE SY-DATUM.
DATA: L_DAYS TYPE I.
DATA: L_DAYS_TIMESTAMP TYPE TIMESTAMPL.
DATA: L_HOUR(2) TYPE N,
L_MIN(2) TYPE N,
L_SEC(2) TYPE N,
L_TIME_TIMESTAMP TYPE TIMESTAMPL.
"THE UNIX EPOCH IS THE TIME 00:00:00 UTC ON 1 JANUARY 1970
L_DATE = '19700101'.
"計算日期與 1970/01/01 差的天數轉換秒數
L_DATE2 = P_WRITEDATE.
L_DAYS = L_DATE2 - L_DATE.
L_DAYS_TIMESTAMP = L_DAYS * 86400. "24(HOURS) * 60(MINUTES) * 60(SECOND)
"計算目前時間的秒數
L_HOUR = P_WRITETIME+0(2).
L_MIN = P_WRITETIME+2(2).
L_SEC = P_WRITETIME+4(2).
L_TIME_TIMESTAMP = L_HOUR * 60 * 60 + L_MIN * 60 + L_SEC.
"計算完目前要累加 or 扣掉的時間 from p_second
L_DAYS_TIMESTAMP = L_DAYS_TIMESTAMP + L_TIME_TIMESTAMP + P_SECOND.
"透過 DIV 86400 取得轉換的天數
L_DAYS = L_DAYS_TIMESTAMP DIV 86400.
L_DATE = L_DATE + L_DAYS.
"透過 MOD 86400 取得扣掉天的剩餘秒數
L_TIME_TIMESTAMP = L_DAYS_TIMESTAMP MOD 86400.
"get hours
L_HOUR = L_TIME_TIMESTAMP DIV 3600.
"透過 MOD 3600 取得扣掉小時的剩餘秒數
L_TIME_TIMESTAMP = L_TIME_TIMESTAMP MOD 3600.
"get minutes
L_MIN = L_TIME_TIMESTAMP DIV 60.
"透過 MOD 60 取得剩餘的秒數
L_TIME_TIMESTAMP = L_TIME_TIMESTAMP MOD 60.
"get second
L_SEC = L_TIME_TIMESTAMP.
C_WRITEDATE = L_DATE.
CONCATENATE L_HOUR ':' L_MIN ':' L_SEC INTO C_WRITETIME.
ENDFORM. " TRANSLATE_UTC0_TO_LOCAL
另外還可以透過 FORM P6_TO_DATE_TIME_TZ(RSTR0400),但因為 P6_TO_DATE_TIME_TZ 傳入的 l_days_timestamp 必需是 UTC+00 的時間,所以除非能夠傳入這個時間,不然傳入的時間有可能會因為目前所在的 Server sy-zonlo 參數而影響傳入的時間
DATA: l_time_timestamp.
DATA: L_GET_TIME(10),
L_GET_DATE LIKE SY-DATUM.
PERFORM P6_TO_DATE_TIME_TZ(RSTR0400) USING l_days_timestamp
L_GET_TIME
L_GET_DATE.
沒有留言:
張貼留言