日付と時刻の計算(SY)
20.2 日付と時刻の計算(SY)
- システム変数
- 日付と時刻の計算
システム変数
ABAP には、SAP システムが自動的に値を設定する「システム変数(システムフィールド)」があります。
たとえば現在日付・現在時刻・ログオンユーザ・直前の命令の実行結果(SY-SUBRC)などが該当します。
主なシステム変数
補足(SY-INDEXとSY-TABIXの違い)
SY-INDEX:DO / WHILE などのループ処理で「何周目か」を表すカウンタ
SY-TABIX:LOOP AT 内部テーブル の処理中に「内部テーブルの何行目か」を表すインデックス
たとえば、内部テーブルに4行あり、DO 3 TIMESの中で LOOP ATを回す場合、
SY-INDEXは 1〜3、SY-TABIXは各周回で1〜4のように変化します。
一方、DO 3 TIMESを外してLOOP ATだけにすると、SY-TABIXは 1〜4 ですが、
この時点のSY-INDEXの値は、直前にDO/WHILEを実行していたならその値のまま残ります。
実行していなければ初期値の0となります。
サンプルコード:SY-INDEX / SY-TABIX 確認
REPORT Z_SAMPLE202_SYLOOP.
"========================================
" テスト用データ(内部テーブル4行)
"========================================
DATA LT_TEST TYPE STANDARD TABLE OF STRING WITH EMPTY KEY.
APPEND 'A' TO LT_TEST.
APPEND 'B' TO LT_TEST.
APPEND 'C' TO LT_TEST.
APPEND 'D' TO LT_TEST.
"========================================
" ケース①:DOの中でLOOP AT(sy-index と sy-tabix が両方変化)
" - sy-index : DO/WHILE のカウンタ(1~2)
" - sy-tabix : LOOP AT 内部テーブルの行番号(各周回で1~4)
"========================================
DO 2 TIMES.
" DOの何周目か(1~2)を確認しやすいように見出しを出す
WRITE: / |--- DO周回: sy-index={ SY-INDEX } ---|.
LOOP AT LT_TEST INTO DATA(LV_VAL).
" sy-index : 今のDOの周回数(1~2)
" sy-tabix : 内部テーブルlt_testの行番号(1~4)
WRITE: / |sy-index={ SY-INDEX }, sy-tabix={ SY-TABIX }, value={ LV_VAL }|.
ENDLOOP.
SKIP.
ENDDO.
"========================================
" ケース②:DOなしでLOOP ATのみ(sy-tabixだけが変化)
" - sy-tabix : LOOP AT の行番号として 1~4
" - sy-index : DO/WHILEを回していないので、このループ中は更新されない
" (直前にDO/WHILEを実行していればその値が残り、
" 実行していなければ初期値の0)
"========================================
SKIP.
WRITE: / '--- DOなし(LOOP ATのみ)---'.
LOOP AT LT_TEST INTO DATA(LV_VAL2).
WRITE: / |sy-index={ SY-INDEX }, sy-tabix={ SY-TABIX }, value={ LV_VAL2 }|.
ENDLOOP.
結果
日付と時刻の計算
日付(D型)は 日単位の加減算ができ、時刻(T型)は「hhmmss(6桁)」として扱われます。
そのため、日付・時刻は計算で求めることができます。
サンプルコード
REPORT Z_SAMPLE202_DATETIME.
START-OF-SELECTION.
"=====================================================
" 日付(D型)は「日単位」で加減算できる
"=====================================================
DATA LV_DATE TYPE D VALUE '20260115'. "基準日(YYYYMMDD)
WRITE: / '入力日付 :', LV_DATE.
"当月1日:日付の「日(dd)」だけを '01' に置き換える
DATA LV_MONTH_BEGIN TYPE D.
LV_MONTH_BEGIN = LV_DATE.
LV_MONTH_BEGIN+6(2) = '01'.
WRITE: / '当月1日(作成) :', LV_MONTH_BEGIN.
"前月末日:当月1日から1日引く(D型は日単位で計算される)
DATA LV_PREV_MONTH_END TYPE D.
LV_PREV_MONTH_END = LV_MONTH_BEGIN - 1.
WRITE: / '前月末日(計算):', LV_PREV_MONTH_END.
SKIP.
"=====================================================
" 時刻(T型)は hhmmss(6桁)として扱える
" → いったん「秒」に変換して引き算し、結果を hhmmss に戻す
"=====================================================
DATA LV_TIME1 TYPE T VALUE '100000'. "10:00:00(6桁)
DATA LV_TIME2 TYPE T VALUE '030000'. "03:00:00(6桁)
WRITE: / '時刻1(入力) :', LV_TIME1,
/ '時刻2(入力) :', LV_TIME2.
"時刻 → 秒(整数)に変換
DATA LV_SEC1 TYPE I.
DATA LV_SEC2 TYPE I.
LV_SEC1 =
CONV I( LV_TIME1+0(2) ) * 3600
+ CONV I( LV_TIME1+2(2) ) * 60
+ CONV I( LV_TIME1+4(2) ).
LV_SEC2 =
CONV I( LV_TIME2+0(2) ) * 3600
+ CONV I( LV_TIME2+2(2) ) * 60
+ CONV I( LV_TIME2+4(2) ).
"差(秒)
DATA LV_DIFF_SEC TYPE I.
LV_DIFF_SEC = LV_SEC1 - LV_SEC2.
"秒 → hhmmss に戻す
DATA LV_HH TYPE I.
DATA LV_MM TYPE I.
DATA LV_SS TYPE I.
LV_HH = LV_DIFF_SEC DIV 3600.
LV_MM = ( LV_DIFF_SEC MOD 3600 ) DIV 60.
LV_SS = LV_DIFF_SEC MOD 60.
"2桁ゼロ埋め(N型を使うと自然に0埋めになる)
DATA LV_HH_TXT TYPE N LENGTH 2.
DATA LV_MM_TXT TYPE N LENGTH 2.
DATA LV_SS_TXT TYPE N LENGTH 2.
LV_HH_TXT = LV_HH.
LV_MM_TXT = LV_MM.
LV_SS_TXT = LV_SS.
DATA LV_TIME_DIFF TYPE T.
LV_TIME_DIFF = LV_HH_TXT && LV_MM_TXT && LV_SS_TXT.
WRITE: / '差(計算結果) :', LV_TIME_DIFF. "07:00:00 相当.
結果(実行時間および環境によって数値が変わります。)