1

我需要计算一个等于两个日期之间“最近”月数的数字。但是,标准 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, Early_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

4

3 回答 3

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;
于 2009-06-25T09:57:37.203 回答
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;

您还可以采用这种方法来计算间隔中的完整月份(“第一个到最后一个”),然后将剩余的天数相加,看看它们的总和是 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 个月)。

于 2009-06-26T15:20:47.823 回答
2

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