日時データ項目の MOVE に関する考慮事項

ここでは、MOVE ステートメント、および暗黙的な移動 (READ INTO、WRITE FROM、REWRITE FROM、RETURN INTO、 および RELEASE FROM) のあるステートメント、および比較条件で日時データ項目を使用するための考慮事項のいくつかを説明します。

@p を大文字に変換する

時刻項目は、@p 変換指定子で定義できます。 この指定子は、AM または PM のいずれかで置き換えることができます。 ただし、AM および PM は、大文字と小文字を任意に組み合わせたものでかまいません。 これは、@p 変換指定子をもつ変換前と受け取り側の両方を含むステートメントでは、変換前には大文字と小文字を混在させることができるが、 受け取り側では、必ず、大文字に変換されるということを意味します。 たとえば、

 01 group-item.
    05 time1 FORMAT TIME "%I:%M @p" VALUE "06:20 am".
    05 time2 LIKE time1.
    MOVE time1 TO time2.
    DISPLAY "time2 = " time2.                        

上のコーディングでは、time1 は MOVE ステートメントの変換前であるため、 その @p 指定子は大文字と小文字が混在していて構いません。 この例では、小文字の am です。 受け取り側 time2 は、time1 と同じ形式をもっているため、@p は大文字で含まれます。 したがって、上のプログラムの出力は、次のようになります。

 time2 = 06:20 AM

2 桁年を 4 桁年または世紀へ変換する

2 桁年を 4 桁年または世紀に移動または比較する場合、 あるいは 4 桁年または世紀を 2 桁年に比較する場合に、ILE COBOL は、 まず最初に、ウィンドウ操作アルゴリズムを使用して 2 桁年を変換します。 使用されるデフォルト・ウィンドウ操作アルゴリズムは、次のとおりです。

注:
日付を含む英数字データ項目が日時データ項目に移動される際には、検査や変換は行われません。 プログラマーは、移動される英数字日付が正しい形式になるようにする必要があります。

この変換がどのように行われるかを示すために、次のプログラムでは 3 つの日付移動を行います。

ID DIVISION.
PROGRAM-ID. datmoves.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
     FORMAT DATE IS '%m/%d/%y'.
DATA DIVISION.
WORKING-STORAGE SECTION.
77  date1  format date Value '07/12/39'.
77  date2  format date '@Y/%m/%d'.
77  date3  format date '%y/%m/%d'.
01  ALPHA_USA_S    PIC X(08).
PROCEDURE DIVISION.
PARA1.
     move date1 to date2.  1 
     display "date2 =" date2.
*
     move date2 to date3.  2 
     display "date3 =" date3.
*
     move FUNCTION ADD-DURATION (date3 YEARS 1) to date2.  3 
     display "date2 =" date2.

このプログラムの出力は、次のとおりです。

 date2 =2039/07/12
 date3 =39/07/12
 date2 =1940/07/12

move  1  では、date1 (値 07/12/39 を含むもの) が date2 に移動されます。 date1 には 40 未満の 2 桁年が含まれており、それが、4 桁年をもつ date2 に移動されるため、 使用される世紀は 2000 で、4 桁年は 2039 となります。

move  2  では、4 桁年が 2 桁年に移動され、世紀 (年の最初の 2 桁) は切り捨てられるだけです。

move  3  では、date3 に 1 年加算されてから、 それが元どおり 4 桁年に移動されます。 加算された年により、日付の 2 桁年は 21 世紀の範囲外に移動されるため、日付は 20 世紀の日付になり、 正確ではありません。 この移動は、ウィンドウ操作アルゴリズムがどのように働くか、 また、4 桁年形式と 2 桁年形式との間で日付を移動するとどのように結果が不正確になるかを示しています。

DATTIM 処理ステートメントのオプションを使用してデフォルト日付ウィンドウを指定変更する

4 桁と 2 桁の年号間でデータを移動する必要があり、移動する時に、ILE COBOL が使用するデフォルトのウィンドウ操作アルゴリズムに基づくと、 間違った結果になることが明らかである場合があります。 DATTIM 処理ステートメントのオプションを使用すると、デフォルト日付ウィンドウを変更できます。

DATTIM 処理ステートメントの構文は、次のとおりです。

構文図を読む構文図をスキップする構文
 
>>-DATTIM--(--4 桁の基本世紀--2 桁の基本年--)------------------><
 

4 桁の基本世紀
これは最初の引き数でなければなりません。 ILE COBOL がそのウィンドウ操作のアルゴリズムで使用する基本世紀を定義します。 DATTIM 処理ステートメント・オプションが指定されていない場合は、1900 が使用されます。

「4 桁の基本世紀」は、@C 変換指定子の変換処理にも影響します。 @C 変換指定子は 1 桁の世紀を表すもので、その範囲は 0 から 9 までです。 1 桁世紀の 0 は 1900 という基本世紀を表し、1 = 2000、... 9 = 2800 という具合です。 したがって、形式が @C/%y/%m で、しかも値が 1/12/05 である日付データ項目は、2012 年の 5 番目の月 (5 月) の最初の日を表します。 ただし、@C が 0 であると、実際に 4 桁の基本世紀に等しくなります。 したがって、DATTIM(2200, 40) は、0 = 2200、1 = 2300 ...、9 = 3100 という具合になります。

2 桁の基本年
これは 2 番目の引き数でなければなりません。 ILE COBOL がそのウィンドウ操作のアルゴリズムで使用する基本年を定義します。 DATTIM 処理ステートメント・オプションが指定されていない場合は、40 が使用されます。

デフォルトの DATTIM(1900, 40) では、1940 から 2039 までの 100 年ウィンドウになります。 先の例で見つかった問題を解決するためには、以下のいずれかの方法で DATTIM オプションを設定できます。

先の例の PROCESS ステートメントにこれらのオプションのいずれかを指定すると、出力は次のようになります。

 date2 =2039/07/12
 date3 =39/07/12
 date2 =2040/07/12

出力で変ったのは、move  3  の結果だけです。 先の例の出力は date2 =1940/07/12 で、これは、 デフォルト ILE COBOL ウィンドウ操作アルゴリズム (1900 という基本世紀と 40 という基本年) に基づいて更新済み 2 桁日付を 4 桁日付に移動した結果であり、不正確なものでした。

日時比較条件のパフォーマンスに関する考慮事項

日時項目が ILE COBOL の別の日時項目に比較される際には、まず最初に、すべての区切り文字が取り払われて、ISO 形式 (区切り文字なし) に変換されます。 次に、2 つの日時項目が、数字ごとに比較されます。 日付同士の比較の場合は、日付が両方とも @Y%m%d に変換されてから、比較されます。 時刻は %H%M%S に変換されてから、比較されます。 これは、日時比較で最良のパフォーマンスを得るためには、日時項目を ISO 形式にする必要があるということを意味しています。

日時移動のパフォーマンスに関する考慮事項

日時項目の形式は、日時移動が完了するのに要する時間の長さに影響します。 基本的な形式を、パフォーマンスの良いものから順に 3 つ挙げると、次のようになります。

  1. 日時項目。 この形式は、iSeries DDS がサポートしている日付、時刻、またはタイム・スタンプ形式と同じです。 このグループの中では、一般的に、ISO 形式のパフォーマンスが最高となります。
  2. 非ロケール日時項目。この形式は 1 には含まれません。
  3. ロケールに基づく日時項目。

マイクロ秒への時間の変換

時刻データ項目には、1 秒未満の秒数を含む指定子を 1 つまたは複数個含めることができます。 1 秒未満の秒数を保持する 4 つの変換指定子は、次のものです。

@Sh
1 秒の 100 分の 1
@Sm
1 秒の 100 万分の 1 (マイクロ秒)
@So
1 秒の 1000 分の 1 (ミリ秒)
@St
1 秒の 10 分の 1

たとえば、時刻データ項目の形式が %H:%M:%S @So/@Sm の場合があります。

時刻データ項目が 2 つあり、一方をもう一方に移動した場合、 送り側のデータ項目の 1 秒未満の秒数を保持する指定子はすべて、マイクロ秒数を表す 1 つの数値に変換されます。 マイクロ秒は、次に、受け取り側の時刻データ項目の適切な 1 秒未満の秒数に変換されます。

時間帯

時刻およびタイム・スタンプのカテゴリーのデータ項目には時間帯の影響があります。 ILE COBOL は、iSeries システム値 QUTCOFFSET (協定世界時オフセット (グリニッジ標準時オフセットとも呼ばれる)) および LC_TOD ロケール から時間帯情報を検索します。 ロケールと関連付けられた時刻データ項目は、LC_TOD ロケール・カテゴリーのキーワード tzdiff で時間帯を使用します。 ロケールと関連付けられていない時刻データ項目およびタイム・スタンプ・データ項目は、iSeries システムの時間帯にあるものと見なされます。 すなわち、QUTCOFFSET システム値によって指定された時間帯に入っています。

したがって、たとえば、次の場合を考えます。

SPECIAL-NAMES.
     LOCALE "EN_US" IN LIBRARY "QSYSLOCALE" IS USA.
   
·
·
·
01 GROUP-ITEM. 05 SYSTEM-TIME-1 FORMAT TIME "%H:%M:%S" VALUE "14:32:10". 05 LOCALE-TIME-1 FORMAT TIME SIZE 8 IS LOCALE USA.
·
·
·
MOVE SYSTEM-TIME-1 TO LOCALE-TIME-1.

iSeries システムに付属している EN_US のロケール・ソースには 0 というデフォルト tzdiff 値が備わっています。 しかし、これは、そのロケール・ソースを別のソース物理ファイルにコピーすることにより、ユーザーが変更できます。 上記の MOVE ステートメントでは、データ項目 SYSTEM-TIME-1 はどのロケールとも関連付けられていないため、 その時間帯は QUTCOFFSET システム値により示されます。 データ項目 LOCALE-TIME-1 はライブラリー QSYSLOCALE 内のロケール EN_US と関連付けられています。 これは、その時間帯が、このロケールの LC_TOD ロケール・カテゴリーで示されることを意味しています。 MOVE ステートメントの実行中、LOCALE-TIME-1 の結果として生じる時刻は、SYSTEM-TIME-1LOCALE-TIME-1 との間の時間帯の差で調整されます。

ILE COBOL では、夏時間を考慮に入れません。 これを適応させるには、LC_TOD ロケール・カテゴリーおよび QUTCOFFSET の協定世界時オフセットを更新して、この時間差を調整する必要があります。

時間帯を考慮に入れる他の組み込み関数は、FIND-DURATION、LOCALE-TIME、および CONVERT-DATE-TIME です。