SAS DATE问题 - 计算“最近一个月”

时间:2009-06-25 09:19:36

标签: date sas

我需要计算一个数字,该数字相当于两个日期之间的“最接近”月数。然而,标准SAS函数(INTCK)不适合考虑其日期参数的DAY(例如,当我需要将其舍入为1时,下面的代码解析为0)。

解决此问题的“最佳”方式是什么?

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) 如果date1是20/3/1997并且date2是23/7/1996

,则返回8

NEAREST_MONTHS(date1,date2) 如果date1是20/3/1997并且date2是1/2/1995

,则返回26

3 个答案:

答案 0 :(得分:2)

您可以使用INTNX查看是否向上或向下舍入,例如


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;

答案 1 :(得分:2)

如果您将月份定义为30天,则可以将15天或更短的时间缩短至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至第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)。

答案 2 :(得分:2)

我把它写成一个函数,我认为它的计算方式与DCS应用程序相同。它使用了9.2版本中SAS的新功能,包括日期中的连续对齐。它也可以在时间上向前或向后工作(即如果early_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