if子句中的日期时间比较

时间:2018-05-28 09:46:05

标签: sas sas-macro

我有以下代码:

%if "&min_date"dt <= "02DEC2014:00:00:00"dt %then %do;
  /* some code */
%end

它并没有像我期望的那样表现。

我的min_date较差,但测试的表达式评估为0

%put &min_date; /* 31JAN1600:00:00:00 */
%put %eval("&min_date"dt <= "02DEC2014:00:00:00"dt); /* 0 */
%put %eval("31JAN1600:00:00:00"dt <= "02DEC2014:00:00:00"dt); /* 0 */

我如何使这项工作?

3 个答案:

答案 0 :(得分:1)

如您所示,%EVAL不知道日期时间文字,因此它将它们视为字符串值。由于%EVAL由%IF语句隐式调用。 %IF语句进行文本比较而不是数字比较。

好消息是%SYSEVALF 确实了解日期时间文字:

%let min_date = 31JAN1600:00:00:00 ; 
%put %sysevalf("&min_date"dt) ;   /*-11357884800*/
%put %sysevalf("&min_date"dt <= "02DEC2014:00:00:00"dt);  /* 1 */
%put %sysevalf("31JAN1600:00:00:00"dt <= "02DEC2014:00:00:00"dt); /* 1 */

在宏%IF中:

%macro test(min_date=) ;
  %if %sysevalf("&min_date"dt <= "02DEC2014:00:00:00"dt) %then %do;
    %put &min_date is less than or equal to "02DEC2014:00:00:00"dt ;
  %end ;
  %else %do ;
    %put &min_date is NOT less than or equal to "02DEC2014:00:00:00"dt ;
  %end ;
%mend ;

返回日志,如:

124  %test(min_date=31JAN1600:00:00:00)
31JAN1600:00:00:00 is less than or equal to "02DEC2014:00:00:00"dt
125  %test(min_date=31JAN2015:00:00:00)
31JAN2015:00:00:00 is NOT less than or equal to "02DEC2014:00:00:00"dt

答案 1 :(得分:1)

实际上,%EVAL()在您的示例中“有效”。 :)不是预期的,但这就是原因:

  • 首先,%EVAL()检查操作数是否可以计算为算术(仅整数)或逻辑。

  • 因为您提供了2个包含非整数字符的日期时间文字,所以它根据字符排序顺序执行了逻辑比较。

%SYSEVALF() - 如前所述 - 将起作用,因为与%EVAL()不同,它支持非整数字符作为操作数并进行额外评估。

%SYSEVALF()支持浮点运算,而%EVAL()只支持整数。

BTW,%EVAL()也用于评估%IF或%DO语句中的表达式等 - 这就是为什么在这些情况下也不支持datetime文字。

注意:考虑到上述情况,通常的好习惯是:

  • 表示整数运算,请使用%EVAL()
  • 用于浮点运算,使用%SYSEVAL()
  • 始终将datetime文字转换为整数,如上面的答案所示,使用%sysfunc(inputn(&amp; datetimeliteral,datetimex。))

其中x将根据日期时间字面值而变化...

答案 2 :(得分:0)

即使您正在使用文字,我认为宏环境会将要比较的值视为字符串 - 它不会尝试在执行比较之前将文字解析为基础数值。如果您希望比较按预期工作,则必须将日期转换为宏语言可以比较的数字,例如

%put %eval(%sysfunc(putn("&min_date"dt,16.)) <= %sysfunc(putn("02DEC2014:00:00:00"dt,16.)));

或者,您可以暂时退出宏语言,然后可以直接使用文字,例如:

%put %eval(%sysfunc(intck(second,"&min_date"dt,"02DEC2014:00:00:00"dt)) > 0);