2009-06-25 42 views
1

我需要計算一個等於兩個日期之間的「最近」月數的數字。然而,標準SAS函數(INTCK)不適合考慮其日期參數的DAY(例如,當我需要將其舍入爲1時,下面的代碼解析爲0)。SAS日期問題 - 計算「最近幾個月」

解決此問題的「最好」方法是什麼?

data _null_; 
    x="01APR08"d; 
    y="28APR08"d; 
    z=intck('MONTH',x,y); 
    put z= ; 
run; 

編輯:對馬丁斯評論的迴應。

我會輪到0個月 - 我不認爲邊界是相關的。我試圖複製的函數(NEAREST_MONTHS)來自DCS(Sungard先知應用程序)。我現在正在等待在應用程序本身中執行一些測試的機會,以更多地瞭解它如何處理日期(將在此處發佈結果))。

幫助文件包含以下內容: 類別 日期

說明

返回月份最接近的數字兩個日期之間的差異。如果第二個日期晚於第一個日期,則返回0。

語法

NEAREST_MONTHS(Later_Date,Earlier_Date)

返回類型 整數

實例

NEAREST_MONTHS(DATE1,DATE2) 返回8如果日期1是20/3/1997和date2是23/7/1996

NEAREST_MONTHS(date1,date2) 如果date1是20/3/1997且date2是1/2/1995,則返回26

+0

這是棘手的,因爲你真的不定義四捨五入規則。例如,您是否希望將30APR09和01MAY09之間的間隔舍入到兩個不同月份之間的邊界之後的1個月內,還是將它舍入到0個月,因爲它只是一個1天的間隔? – 2009-06-26 14:28:56

回答

2

我寫了這個函數,我認爲它和DCS應用程序的計算方法相同。它使用了9.2版本中的一些新功能,包括日期中的連續對齊。它也能及時向前或向後運行(即如果earlier_date在later_date之後,則給出負整數)。我使用超過間隔15天以上的截止時間來輪到下個月,但如果您願意,可以調整此值。

proc fcmp outlib=work.myfuncs.dates; 
    function nearest_months(later_date,earlier_date); 
     /* Return missing if inputs are missing */ 
     if (earlier_date eq .) OR (later_date eq .) then 
      nearest_month=.; 
     else do; 
      /* Use 'cont' argument for continuous dates */ 
      months=intck('MONTH',earlier_date,later_date,'cont'); 
      if months < 0 then months=months+1; 
      days= later_date - intnx('month', earlier_date,months,'same'); 

      /* Handle negatives (earlier dates) */ 
      if months < 0 then do; 
       if days < -15 then months=months-1; 
       nearest_month=months; 
       end; 
      else do; 
       if days > 15 then months + 1; 
       nearest_month=months; 
       end; 
     end; 
     return(nearest_month); 
    endsub; 
run; 
options cmplib=work.myfuncs; 


data _null_; 
x=nearest_months('20Mar1997'd, '23JUL1996'd); 
put x=; 
x=nearest_months('20Mar1997'd, '01FEB1995'd); 
put x=; 
run; 

這給出了同樣作爲您的參考:

x=8 
x=26 
2

如果要查看是否向上取整或向下取整,


data _null_; 
    format x y date9. z 8.; 
    x="01APR08"d; 
    y="28APR08"d; 
    z=intck('MONTH',x,y); 

    * wl is x + z months; 
    wl=intnx('MONTH',x,z); 

    * wu is x + (z+1) months; 
    wu=intnx('MONTH',x,z+1); 

    * If y is closer to wu, then adjust z by 1; 
    if (abs(y-wu) lt abs(y-wl)) then z = z+1;  

    put x y z=; 
run; 
+0

您的代碼會將30APR09和01MAY09之間的時間間隔評估爲1個月,但由於只有1天,因此我會親自調整爲0個月。 它也評估30APR09和01JUN09之間的時間間隔爲2個月,但我會將它週期爲1個月,因爲它是1個月和1天。 – 2009-06-26 14:25:33

2

如果定義一個月爲30天,你將圓十五日以下降到0個月和16天以上至1個月。 這可以通過以下方式實現以下幾點:

data _null_; 
    format x y date9. z 8.; 
    x="14FEB09"d; 
    y="02MAR09"d; 

    z=round(intck('DAY',x,y)/31); 
    put x y z=; 
run; 

你也可以採取的方法來算整月(「第一1日至最後一日」)的時間間隔,然後加起來剩餘天數,看是否他們總計0,1或2個月。 像這樣:

data _null_; 
    format x y date9. z 8.; 
    x="01FEB09"d; 
    y="31MAR09"d; 

    if day(x)=1 then do; 
    z=intck('MONTH',x,intnx('MONTH',y,0,'BEGINNING')) 
     + round((intck('DAY',intnx('MONTH',y,0,'BEGINNING'),y))/31); 
    end; 
    else do; 
    z=intck('MONTH',intnx('MONTH',x,1,'BEGINNING'),intnx('MONTH',y,0,'BEGINNING')) 
     + round((intck('DAY',x,intnx('MONTH',x,1,'BEGINNING'))+intck('DAY',intnx('MONTH',y,0,'BEGINNING'),y))/31); 
    end; 
    put x y z=; 
run; 

第一種方法是比較容易理解和維護,但第二大間隔的更準確的(01FEB06到01FEB09爲36個月,但方法1會告訴你,這只是35)。