日付と時刻の計算(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 相当. 
結果(実行時間および環境によって数値が変わります。)

NEXT>> 20.3 練習問題(繰り返し処理)

研修の詳細はこちら