Migaro. 技術Tips

                       

ミガロ. 製品の技術情報
IBMiの活用に役立つ情報を掲載!


IBMiの日付データを簡単に変換する方法(日付型⇔文字 日付型⇔数値)

IBMi(DB2 for i)では、日付のデータを数値型のフィールド8桁で、保持している場合が多く見受けられます。数値型の場合は、日付の計算(差分や追加等)をRPGのロジックで作成する必要があるため、ステップ数も多くて、プログラムも複雑になりがちです。IBMiでは、日付型(L)を利用すると簡単に日付の計算を行うことができます。
今回のTipsでは、日付型と数値、日付型と文字列等 RPGLEでの変換方法とValenceのデータソースで数値を日付型として扱う方法についてご紹介します。

日付型に変更して処理することのメリット

IBMiでは、数値で日付データをファイルに保持している場合が多いです。
数値で扱う場合、数日後の日付を取得するといった、日付の計算時にうるう年の概念や、月をまたぐ場合、年をまたぐ場合、などの計算をRPGロジックで記述する必要があるため複雑になります。

日付型に変換すると、数日後の日付を取得する場合でも、追加する日数を日付型フィールドに対して「足す」処理だけで、うるう年のような複雑なロジックがなくても、正しい日付を取得できます。

Tipsでは、以下をご紹介します。

  • 数値や文字列を日付型へ変換する方法
  • 日付型の計算方法
  • 日付型を数値や文字に変換する方法
  • Valenceのデータソースで数値や文字列を日付型に変換する方法

数値や文字列を日付型へ変換する方法

数値8桁のフィールドを日付型に変換

数値8桁の日付を日付型に変換する場合、%DATEを使用すると簡単に変換可能です。

     D NUM8DATE        S              8S 0
     D ISODATE         S               D   DATFMT(*ISO)
      *
     C                   Z-ADD     20220722      NUM8DATE
      /free
              ISODATE  = %DATE(NUM8DATE:*ISO);
              DSPLY %CHAR(ISODATE);
      /end-free
    C                   SETON                                        LR

上記コードでは、数値フィールド「NUM8DATE」に格納されている8桁の数値(20220722)を日付型に変換します。
「%DATE関数」で数値8桁を「日付データ・タイプ」*ISO形式に変換して、日付型フィールドの「ISODATE」に格納しています。

%DATE関数 サンプルの実行結果

このプログラムを実行すると以下のように*ISO形式 (YYYY-MM-DD)に変換されている結果が確認できます。

◆%DATE (日付への変換)
https://www.ibm.com/docs/ja/i/7.2?topic=functions-date-convert-date#bbdate

数値6桁のフィールドを日付型に変換

日付のデータを数値6桁で保持している場合もあると思います。
その場合は、数値8桁の場合と同じで%DATE関数を使用して、日付データ・タイプを*YMD形式(YY/MM/DD)にすれば、日付型に変換できます。

     D NUM6DATE        S              6S 0
     D YMDDATE         S               D   DATFMT(*YMD)
      *
     C                   Z-ADD     220725        NUM6DATE
      /free
              YMDDATE  = %DATE(NUM6DATE:*YMD);
              DSPLY %CHAR(YMDDATE);
      /end-free
     C                   SETON                                        LR

他にも、IBMiの日付データ・タイプは様々あります。
詳細は以下、IBMのサイトご確認ください。

◆日付データ・タイプ
https://www.ibm.com/docs/ja/i/7.5?topic=formats-date-data-type

文字列を日付型に変更する方法

文字列10桁のフィールドを日付型に変換

文字列の場合も、数値と同様に%DATE関数を使用することで簡単に日付型へ変更できます。
数値の場合と同様に、%DATE関数の第2引数(日付データ・タイプ)指定により様々な形式の文字列を日付型に変換できます。
ただし、文字列を変換する場合は、日付の区切り文字を考慮する必要があるため注意ください。
 ※第一引数、日付文字列の桁数や、区切り文字に注意して、第2引数の「日付データ・タイプ」を指定

     D STR10DATE       S             10A
     D ISODATE         S               D   DATFMT(*ISO)
      *
     C                   MOVEL(P)  '2022-07-22'  STR10DATE
      /free
              ISODATE  = %DATE(STR10DATE:*ISO);
              DSPLY %CHAR(ISODATE);
      /end-free
     C                   SETON                                        LR

日付型の計算方法

日付の加算と減算

日付型に変換すると、日付の加算、減算が簡単に行えます。
加算であれば、「+」 、減算であれば、「-」で日付を計算します。
例えば、以下のプログラム例では、2022年7月22日の100日後の日付を表示します。

     D NUM8DATE        S              8S 0
     D ISODATE         S               D   DATFMT(*ISO)
     D RSTDATE         S               D   DATFMT(*ISO)
      *
     C                   Z-ADD     20220722      NUM8DATE
      /free
              ISODATE  =  %DATE(NUM8DATE:*ISO);
              RSTDATE  =  ISODATE + %DAYS(100);
              DSPLY %CHAR(RSTDATE);
      /end-free
     C
     C                   SETON                                        LR

%DAYS(100)と記述しているのが、100日の表現になります。
他にも、「年」単位や「月」単位でも計算が可能です。

  • %YEARS : 年単位
  • %MONTHS : 月単位
  • %DAYS : 日単位

例えば、2年後では以下です。

              RSTDATE  =  ISODATE + %YEARS(2);

2か月前では以下のようになります。

              RSTDATE  =  ISODATE - %MONTHS(2);

日付型を数値や文字に変換する方法

計算した日付を再度、ファイルに保存し直す場合、日付型を再度、数値型や文字型に変換する必要があるかと思います。

日付型を文字列に変換

文字に変換するのは簡単で、%CHARを利用するだけです。
日付型フィールドの「日付データ・タイプ」の形式で文字列を取得できます。

ISODATEが「2022-07-22」の場合、2日後の「2022-07-24」がRSTDATE に格納されます。
文字列の変換は%CHARを使用するだけです。
STRDATEに10桁の文字列 2022-07-24 が格納されます。

              RSTDATE  =  ISODATE + %DAYS(2);
              STRDATE  =  %CHAR(RSTDATE);

日付型を数値に変換

日付型を数値に変換するには%DEC関数を使用します。
%DEC関数は第1引数に数値や文字列だけでなく、日付型/時刻型/タイムスタンプ型を設定することも可能です。

◆%DEC(パック10進数への変換)
https://www.ibm.com/docs/ja/i/7.3?topic=functions-dec-convert-packed-decimal-format

以下の例では、2022年07月22日の4日後をRSTDATEフィールドに格納後、%DECを使用してNUMDATEフィールドに数値8桁 20220722を返却しています。

     D NUM8DATE        S              8S 0
     D ISODATE         S               D   DATFMT(*ISO)
     D RSTDATE         S               D   DATFMT(*ISO)
     D NUMDATE         S              8S 0
      *
     C                   Z-ADD     20220725      NUM8DATE
      /free
              ISODATE  =  %DATE(NUM8DATE:*ISO);
              RSTDATE  =  ISODATE + %DAYS(4);
              NUMDATE  =  %DEC(RSTDATE);
              DSPLY  %CHAR(NUMDATE);
      /end-free
     C                   SETON                                        LR

%DEC関数では、第2引数を設定することで、明示的に8桁数値や、6桁の数値、また、フォーマットを変換して取得することができます。
第2引数に「日付データ・タイプ」を指定することで、様々な形式の数値として取得ができます。

例えば、RSTDATEフィールドが 日付(2022年07月25日)の場合には以下になります。

  • 第2引数*ISO:NUMDATEには、8桁の数値20220725が格納されます。
              NUMDATE  =  %DEC(RSTDATE:*ISO);
  • 第2引数*YMD:NUMDATEには、6桁の数値220725が格納されます。
              NUMDATE  =  %DEC(RSTDATE:*YMD);

Valenceのデータソースで数値や文字列を日付型に変換する方法

Valenceのデータソースでは、計算項目にて、SQLスカラー関数を使用して、文字列操作処理等で日付型に変換できます。

Valence 計算項目

数値8桁を日付に変換するには以下のような「計算項目」になります。
  ※F1.VTSTYPは数値8桁のフィールドです。環境に合わせてフィールド名をご変更ください。

DATE(SUBSTR(CHAR(TIMESTAMP_FORMAT(CHAR(F1.VTSTYP),'YYYYMMDD')),1,10 ))

上記では、全てのデータが日付に変換できる必要があります。
そのため、データによっては、次の例のように文字列として分割して、変換が必要となる場合もあります。

DATE(substr(char(F1.VTSTYP), 1, 4) || '-' || substr(char(F1.VTSTYP), 5, 2) || '-' || substr(char(F1.VTSTYP), 7, 2))

上記例であれば、F1.VTSTYPフィールドが文字列だった場合にも対応可能です。

おわりに

今回のTipsは、数値や文字列のデータを日付型へ変換する方法についてご紹介しました。
日付型に変換することで、日付の加算や減算処理などが簡単に行えることをご理解いただけたと思います。Valenceでは、日付型としてフィールドを定義することで、カレンダーの機能を利用できるという利点もあるので、データソース作成時に日付型に変換する方法をご活用頂ければ幸いです。