前のページ|次のページ

日付間隔と時間間隔

日付間隔と時間間隔の定義

間隔とは、日、月または時間などの経過期間内でSASが計測する測定単位です。SASでは、日付と時間の間隔をカレンダ上またはクロック上の固定点に基づいて決定します。間隔計算の開始点は、デフォルトで開始値が入る期間の開始時点となります。これは、指定された実際の開始値とは異なる場合があります。たとえば、2つの日付間の月数を数えるのにINTCK関数を使用する場合、開始値の日付に指定した日付が実際にその月の何日であるかにはかかわらず、SASは開始値を該当月の初日として扱います。

間隔名とSAS日付

SAS日付値で使用する特定の間隔名もあれば、SAS時間値およびSAS日時値で使用する間隔名もあります。SAS日付値で使用する間隔名にはYEAR、SEMIYEAR、QTR、MONTH、SEMIMONTH、TENDAY、WEEK、WEEKDAY、DAYがあります。SAS時間値およびSAS日時値で使用する間隔名にはHOUR、MINUTEおよびSECONDがあります。
SAS日付値に使用される間隔名に、'DT'を接頭辞として付加した間隔名を作成して、SAS日時値で使用できます。間隔名DTYEAR、DTSEMIYEAR、DTQTR、DTMONTH、DTSEMIMONTH、DTTENDAY、DTWEEK、DTWEEKDAY、DTDAY、はSAS時間値またはSAS日時値で使用します。

乗数とシフト間隔を使用した日時の増分

各種の経過時間を数えるための日付、時間および日時の間隔がSASには用意されています。乗数とシフトインデックスを使用することで間隔の倍数を作成し、開始点をシフトしてより複雑な間隔指定を作成できます。
間隔名の一般的な形式を次に示します。
name<multiplier><.shift-index>
引数multipliershift–index引数は省略可能で、デフォルトは1です。たとえば、YEAR、YEAR1、YEAR.1、YEAR1.1は、すべてが同様に1月から始まる通常のカレンダ年を指定する方法です。multipliershift-indexに他の値を指定すると、1年で異なる時期に始まる複数の間隔を作成できます。たとえば、WEEK6.11という間隔指定は、第2水曜日を開始時点とする6週間隔です。
詳細については、Single-Unit Intervals (SAS言語リファレンス: 解説編) Multi-Unit Intervals (SAS言語リファレンス: 解説編)およびShifted Intervals (SAS言語リファレンス: 解説編)を参照してください。

よく使用される時間間隔

年または日にネストできない時間間隔は、SAS日付値またはSAS日時値ゼロと相対的に調整されます。SASでは、シフトされていない間隔の起点として、1960年1月1日を参照時間に任意で定めています。シフトされている間隔については、1960年1月1日との相対で定義されます。
たとえば、MONTH13は1960年1月1日、1961年2月1日、1962年3月1日と続く間隔と、基準日1960年1月1日以前の1958年12月1日、1957年11月1日と続く間隔を定義します。
もう1つの例として、WEEK6.13という間隔指定は、第2金曜日を開始時点とする6週間隔を定義します。相対的な調整を1960年1月1日を含む期間に対して行うというこの規則によって、6週間隔の第2金曜日がどの日付に対応するかが決定します。
よく使用される時間間隔を次の表に示します。
よく使用される間隔と省略可能な乗数およびシフトインデックス
間隔
説明
DAY3
3日間隔
WEEK
日曜日を開始時点とする週間隔
WEEK.7
土曜日を開始時点とする週間隔
WEEK6.13
第2金曜日を開始時点とする6週間隔
WEEK2
第1日曜日を開始時点とする隔週間隔
WEEK1.1
WEEKと同じ
WEEK.2
月曜日を開始時点とする週間隔
WEEK6.3
第1火曜日を開始時点とする6週間隔
WEEK6.11
第2水曜日を開始時点とする6週間隔
WEEK4
第1日曜日を開始時点とする4週間隔
WEEKDAY
土曜日と日曜日を週末、5日間を就業日とする週
WEEKDAY1W
日曜日を週末日、6日間を就業日とする週
WEEKDAY35W
火曜日と木曜日を週末日とし、5日間を就業日とする週(Wで3日目と5日目を週末日に指定)
WEEKDAY17W
WEEKDAYと同じ
WEEKDAY67W
金曜日と土曜日を週末日とする5日間の週
WEEKDAY3.2
土曜日と日曜日を週末日とする3平日間隔(間隔は1960年1月1日を基準として調整されます。同一年にネストされる間隔については、1960年1月1日にさかのぼって調整の必要はありません)
TENDAY4.2
TENDAY単位の2番目を開始時点とする40日単位
SEMIMONTH2.2
月の16日目から翌月の15日目までの間隔
MONTH2.2
2月-3月、4月-5月、6月-7月、8月-9月、10月-11月、12月-1月(翌年)
MONTH2
1月-2月、3月-4月、5月-6月、7月-8月、9月-10月、11月-12月
QTR3.2
1960年2月1日、1960年11月1日、1961年8月1日、1962年5月1日と続く9か月間隔
SEMIYEAR.3
6か月間隔、3月-8月および9月-2月
YEAR.10
10月に開始する会計年度
YEAR2.7
偶数年の7月を開始時点とする隔年間隔
YEAR2.19
奇数年の7月を開始時点とする隔年間隔
YEAR4.11
うるう年の11月を開始時点とする4年間隔(米国の大統領選挙の周期)
YEAR4.35
うるう年間の偶数年の11月を開始時点とする4年間隔(米国の中間選挙の周期)
DTMONTH13
1960年1月1日午前零時を開始時点とする13か月間隔。1957年11月1日、1958年12月1日、1960年1月1日、1961年2月1日、1962年3月1日など
HOUR8.7
午前6時、午後2時および午後10時を開始時点とする8時間間隔 (就業シフトに使えます)
intervalの有効な値の完全なリストについては、Intervals Used with Date and Time Functions (SAS言語リファレンス: 解説編)を参照してください。

販売カレンダの間隔:ISO 8601準拠

小売業界では、1年のカレンダを13週間からなる4つの期間に分けてデータを計算することがよくあります。期間の形式は、4-4-5、4-5-4または5-4-4のいずれかに基づきます。1番目、2番目および3番目の数字は、それぞれ1番目、2番目および3番目の期間に何週間あるかを指定します。
これらの形式から作成される間隔は、INTCINDEX、INTCK、INTCYCLE、INTFIT、INTFMT、INTGET、INTINDEX、INTNX、INTSEAS、INTSHIFTのいずれの関数でも使用できます。
詳細については、Retail Calendar Intervals: ISO 8601 Compliant (SAS言語リファレンス: 解説編)を参照してください。

カスタム時間間隔

カスタム時間間隔を使用する理由

標準の時間間隔(たとえば、QTR、MONTHおよびWEEKなど)は、必ずしもデータに適合しません。また、標準の間隔で計測された時系列の中には、データ中にギャップが含まれているものもあります。たとえば、会計月を毎月10日に開始するとします。この場合、MONTH間隔は毎月1日に始まるため、MONTH間隔を使うのは適切ではありません。カスタム間隔を使用し、ビジネスとの親和性が高い周期でデータをモデリングし、圧縮によってデータ中のギャップを削除します。間隔は昇順で記述する必要があります。間隔には、間にギャップがあったり、重なり合ったりはできません。
もう1つの例として、夜間は営業しないビジネスのデータを1時間ごとに収集するとします。この場合、DTHOUR間隔を使用するとデータにギャップが生じ、標準の時系列分析で問題が発生する原因となる場合があります。また、日付間の営業日数を、祝日と週末を除いて数えるとします。ただし、祝日が数えられるのは、INTCK関数をWEEKDAY間隔と使用するときです。このような場合にカスタム間隔の使用が有効です。

SASプログラムでカスタム時間間隔を使用する

カスタム間隔はSASプログラム内のデータセットで定義できます。カスタム間隔を使用するには、各間隔で2つの操作を実行する必要があります。
  1. INTERVALDS=システムオプションをOPTIONSステートメントで使用し、データセット名とカスタム間隔名を関連付けます。
    INTERVALDS=システムオプションの引数の例を次に示します。ここでは、データセットStoreHoursDSとカスタム間隔StoreHoursを関連付けています。
    options intervalds=(StoreHours, StoreHoursDS); 
    詳細については、INTERVALDS= System Option (SASシステムオプション: リファレンス)を参照してください。
  2. カスタム間隔を説明するデータセットを作成します。
    データセットにはbegin変数を含める必要があり、end変数とseason変数を含めることもできます。SASプログラムにFORMATステートメントを使用し、begin変数と関連付ける必要があります。begin変数データに一致するSAS日付出力形式、SAS日時出力形式またはSAS数値出力形式を指定します。end変数が存在する場合は、それをFORMATステートメントに含めます。SAS日付またはSAS日時形式でない数値形式は、値がオブザベーション番号を示します。end変数が存在しない場合は、次のオブザベーションのbegin値より1少ない値が、それぞれのオブザベーションのendの暗黙値となります。
    カスタム間隔データセットの期間には、時系列でのバックキャスティングやフォーキャスティングなどの計算の実行に加え、時系列の範囲外にまたがって行う可能性のあるその他の処理の実行に必要な日付または時間を含めます。
前述の手順に従ってカスタム間隔を定義した後は、SASプロシジャと関数で、標準時間間隔の指定が可能な場所にカスタム間隔を指定できます。
注: ネストされたカスタム間隔はサポートされません。
次の例では、一部の日付関数と時間関数の使用方法を示します。また、SAS Press書籍抜粋SAS Functions by Example(Ron Cody著)にも追加例があります。このSAS Press書籍には、およそ200関数の情報が含まれています。また、Ronは省略可能な引数に関しても多くの例や詳細を収録しています。

例1:ビジネス展開している店舗の営業時間をINTNX関数で作成する

次のDATAステップは、月曜日から金曜日までの午前9時から午後6時と、土曜日の午前9時から午後1時までを営業時間とする、あるビジネスのStoreHoursDSデータセットを作成します。ここではINTNX関数を使用し、指定した時間間隔で日付値、時間値または日時値を増分し、日付値、時間値または日時値を返します。この例では、StoreHoursが間隔、StoreHoursDSがユーザー指定の祝日を含むデータセットです。
options intervalds=(StoreHours=StoreHoursDS);
data StoreHoursDS(keep=begin end);
   start = '01JAN2009'd;
   stop  = '31DEC2009'd;
   do date = start to stop;
      dow = weekday(date);
      datetime=dhms(date,0,0,0);
      if dow not in (1,7) then 
         do hour = 9 to 17;
            begin=intnx('hour',datetime,hour,'b');
            end=intnx('hour',datetime,hour,'e');
            output;
         end;
      else if dow = 7 then 
         do hour = 9 to 12;
            begin=intnx('hour',datetime,hour,'b');
            end=intnx('hour',datetime,hour,'e');
            output;
         end;
   end;
   format begin end datetime.;
run;
title 'Store Hours Custom Interval';

proc print data=StoreHoursDS (obs=18);
run;
この出力は、カスタム間隔データセットの最初の18のオブザベーションを示しています。
店舗営業時間のカスタム間隔
店舗営業時間のカスタム間隔

例2:会計月のカスタム間隔をINTNX関数で作成する

次のDATAステップは、カスタム間隔FiscalMonthを定義するFMDSデータセットを作成します。これは会計月が毎月10日に始まるビジネスに対応します。INTNX関数のSAME配置オプションで、INTNX関数で生成される月の日付がstart変数の日付と同じになるように指定します。MONTH関数はbegin変数の月をseason変数に割り当て、月単位の季節性を指定します。
options intervalds=(FiscalMonth=FMDS);
data FMDS(keep=begin season);
   start = '10JAN1999'd;
   stop  = '10JAN2001'd;
   nmonths = intck('month',start,stop);
   do i=0 to nmonths;
      begin = intnx('month',start,i,'S');
      season = month(begin);
      output;
   end;
   format begin date9.;
run;

proc print data=FMDS;
   title 'Fiscal Month Data';
run;
会計月のデータ
会計月のデータ
カスタム間隔のFiscalMonthと標準の間隔の違いは次の例で確認できます。このプログラムの出力は、データの累計方法を比較します。FiscalMonth間隔では、前月に始まる間隔に月の最初の9日間の値が累計されています。標準のMONTH間隔では、カレンダ月に従って月の最初の9日間の値が累計されています。
data sales(keep=date sales);
   do date = '01JAN2000'd to '31DEC2000'd;
      month = MONTH(date);
      dayofmonth = DAY(date);
      sales = 0;
      if (dayofmonth lt 10) then sales= month/9;
      output;
   end;
   format date monyy.;
run;

proc timeseries data=sales out=dataInFiscalMonths;
   id date interval=FiscalMonth accumulate=total;
   var sales;
run;

proc timeseries data=sales out=dataInStdMonths;
   id date interval=Month accumulate=total;
   var sales;
run;

data compare;
   merge dataInFiscalMonths(rename=(sales=FM_sales))
         dataInStdMonths(rename=(sales=SM_sales));
   by date;
run;

title 'Standard Monthly Data and Fiscal Month Data';

proc print data=compare;
run;
標準の月次データと会計月データの比較
標準の月次データと会計月データの比較

例3:INTCK関数でカスタム間隔を使用する

次の例では、INTCK関数でカスタム間隔を使用し、営業日を数える場合に祝日を除いています。
options intervalds=(BankingDays=BankDayDS);
data BankDayDS(keep=begin);
   start = '15DEC1998'd;
   stop  = '15JAN2002'd;
   nwkdays = intck('weekday',start,stop);
   do i = 0 to nwkdays;
      begin = intnx('weekday',start,i);
      year = year(begin);
      if begin ne holiday('NEWYEAR',year) and 
         begin ne holiday('MLK',year) and 
         begin ne holiday('USPRESIDENTS',year) and 
         begin ne holiday('MEMORIAL',year) and 
         begin ne holiday('USINDEPENDENCE',year) and 
         begin ne holiday('LABOR',year) and 
         begin ne holiday('COLUMBUS',year) and 
         begin ne holiday('VETERANS',year) and 
         begin ne holiday('THANKSGIVING',year) and 
         begin ne holiday('CHRISTMAS',year) then
      output;
   end;
   format begin date9.;
run;
data CountDays;
   start = '01JAN1999'd;
   stop  = '31DEC2001'd;
   ActualDays = intck('DAYS',start,stop);
   Weekdays   = intck('WEEKDAYS',start,stop);
   BankDays   = intck('BankingDays',start,stop);
   format start stop date9.;
run;

title 'Methods of Counting Days';

proc print data=CountDays;
run;
銀行営業日のカスタム間隔
銀行営業日のカスタム間隔

カスタム間隔名のベストプラクティス

カスタム間隔名を作成するときのベストプラクティスを次の各項目に示します。
  • カスタム間隔名が既存のSAS間隔名と競合しないようにします。たとえば、仮にBASEというSAS間隔名がある場合は、次の形式をカスタム間隔名に使用しないようにします。
    • BASE
    • BASEm
    • BASEm.n
    • DTBASE
    • DTBASEm
    • DTBASEm.n
    次のパラグラフでは変数について説明します。
    m
    乗数を指定します(省略可能)。基本タイプの間隔の期間に対する倍数と同等の間隔を設定します。たとえば、間隔YEAR2は2年の期間の間隔、つまり隔年です。
    n
    シフトインデックスを指定します(省略可能)。間隔の開始時点を指定したサブ期間にシフトします。たとえば、YEAR.3を指定すると1年の期間がシフトされて、毎年カレンダ年の3月1日に開始し、翌年の2月末に終了します。
    CUSTBASEのようなカスタム間隔を定義すると、CUSTBASEm.nを使用できます。
    これらの規則があるため、カスタム間隔名の先頭にDTを付けたり、カスタム間隔名の末尾に数字を付けたりしないでください。
  • カスタム間隔を安定して動作させるには、次のいずれかの形式を使う必要があります。
    date-format(開始値および終了値に使用)
    SAS日付値で使用する間隔を指定します。
    datetime-format(開始値および終了値に使用)
    SAS日時値で使用する間隔を指定します。
    number-format(開始値および終了値に使用)
    SAS日時値で使用するオブザベーション番号を指定します。
  • 開始値と終了値は同じ種類である必要があります。つまり、両方の値を日付値、日時値またはオブザベーション番号とします。
  • カスタム間隔の計算は、最初の開始値より前、または最後の終了値より後で実行できません。開始変数のみを使用すると、計算できる最後の終了値は、最後の開始値である-1です。時系列をフォーキャストまたはバックキャストする場合は、フォーキャスト値とバックキャスト値の時間定義が必要です。
  • CUSTBASEm.2は、定義上、最初の間隔の開始がデータセットの開始よりも前(– (m– 2)番目のオブザベーション)となるため、最初に日付値を求めるための開始期間を計算できません。たとえば、CUSTBASE4.2という間隔があるとします。最初の間隔は最初のオブザベーションよりも前に開始します。
    OBS
    -2    Start of partial CUSTBASE4.2 interval observation:  -(4-2) = -2.
    -1
    0
    1     End of partial CUSTBASE4.2 interval observation: This is the first 
           observation in the data set.
    2     Start of first complete CUSTBASE4.2 interval.
    3
    4
    5     End of first complete CUSTBASE4.2 interval.
    6     Start of 2nd CUSTBASE4.2 interval.
    INTNX関数を実行すると結果にはOBS –2に関連付けられる日付を返す必要がありますが、その日付は存在しません。
    INTNX('CUSTBASE4.2', date-at-obs1, 0, 'B');
  • 季節性インデックスを定義するカスタム間隔データセットにはseasonと名付けた変数を含めます。この結果は、次のコードと似た結果になります。INTINDEX ('interval', date);
    次の例では、データセットはカスタム間隔CUSTWEEKと関連付けられています。
    Obs        begin                    season
        1             27DEC59          52
        2             03JAN60            1
        3             10JAN60            2
        4             17JAN60            3
        5             24JAN60            4
        6             31JAN60            5
    
    カスタム間隔関数を使用したときの結果例を次に示します。
    INTINDEX ('CUSTWEEK', '03JAN60'D);
    値1を返します。
    INTSEAS ('CUSTWEEK');
    季節で最大の値である値52を返します。
    INTCYCLE ('CUSTWEEK');
    CUSTWEEK52を返します。これはCUSTBASEmax(season)です。
    INTCINDEX ('CUSTWEEK', '27DEC59'D);
    値1を返します。
    INTCINDEX('CUSTWEEK', '03JAN60'D)
    値2を返します。
    季節がseasonの前の値より小さくなると、新しい周期が始まります。
  • 季節性は、season1、season2、season3などと、季節が識別されると生じます。すべての季節がseason1と識別されると、季節性は存在しません。また、トリビアルな季節性と呼ばれる季節性も存在しません。
    トリビアルな季節性を利用できるのは、CUSTBASEmの形式の間隔のみです。seasonがデータセットに含まれていない場合、トリビアルな季節性が有効です。
  • begin変数の形式がデータセットに含まれている場合、INTFMT ('CUSTBASE', 'l')またはINTFMT ('CUSTBASE', 's')によって生成されるメッセージが表示されます。データセットで指定されている形式に基づく形式を勧めるメッセージが表示されます。
  • INTSHIFT ('CUSTBASE');またはINTSHIFT ('CUSTBASEm.s'); を実行すると、CUSTBASEの値が返されます。
  • 間隔CUSTBASE、CUSTBASEmおよびCUSTBASEm.sは、INTNX、INTCKおよびINTTESTと使用すると期待通りに機能します。
前のページ|次のページ|ページの先頭へ