SAS宏变量不同日期格式转换及NOTE 49-169问题排查
问题根因
两个独立问题同时存在,不要混淆:
NOTE 49-169提示本身不阻断程序运行,属于SAS对未来版本语法兼容性的提示:触发原因是宏语句末尾的结束分号和后续块注释/*之间没有留空白字符,SAS词法扫描器无法直接判定后面的/是注释开头还是标识符/运算符的一部分,只要在分号和注释之间加一个空格即可消除该提示。- 无法得到预期宏变量值的核心原因是SAS函数、格式的用法错误:
- 函数作用搞反:
inputn()的作用是把字符值按指定输入格式(informat)转为数值,你最终需要的是字符型结果用于拼接表名,应该用putn()把SAS日期数值按指定输出格式(format)转为字符。 - 格式与待处理值不匹配:第一行生成的
GL_YMD是31JAN2009这类DATE9.格式的字符串,后续用YYMMDD8.、YYYYMM这类格式去读取该字符串,格式规则完全不匹配,只会返回缺失值。 - 冗余转换:第一行已经把原始SAS日期值(本质是存储距1960年1月1日天数的数值)转成了DATE9.格式的字符,后续再转其他格式需要先转回日期数值,属于不必要的冗余操作。
- 格式选错:SAS中输出无分隔符的8位年月日、6位年月,需要用带
n(无分隔符)后缀的专用格式,直接用输入格式做输出会返回带横杠的结果,不符合拼接表名的需求。
- 函数作用搞反:
修正代码
最优写法是先存储原始SAS日期数值,后续所有格式转换直接基于该数值用putn()输出目标字符,注释前留空格消除提示:
/* 先存基准日期的原始SAS日期数值,不提前做格式转换 */ %LET GL_DATE = %sysfunc(mdy(1,31,2009)); /* 转DATE9.格式字符,结果为31JAN2009 */ %LET GL_YMD = %sysfunc(putn(&GL_DATE, date9.)); /* 分号和注释间留空格,不会触发兼容性提示 */ /* 转8位无分隔符年月日,结果为20090131,注意用yymmddn8.而非YYMMDD8. */ %LET YYYYMMDD = %sysfunc(putn(&GL_DATE, yymmddn8.)); /* 转6位无分隔符年月,结果为200901,注意用yymmn6.而非YYYYMM */ %LET YYYYMM = %sysfunc(putn(&GL_DATE, yymmn6.)); /* 日志打印验证结果 */ %put &=GL_YMD; %put &=YYYYMMDD; %put &=YYYYMM;
运行后日志输出符合预期:
GL_YMD=31JAN2009 YYYYMMDD=20090131 YYYYMM=200901
如果你一定要保留第一行直接生成GL_YMD的写法,需要先把DATE9.格式的字符转回日期数值,再做格式输出(不推荐,多了一层冗余转换):
%LET GL_YMD= %sysfunc(mdy(1,31,2009),date9.); /* 分号和注释间留空格消除提示 */ %LET YYYYMMDD= %sysfunc(putn(%sysfunc(inputn(&GL_YMD,date9.)),yymmddn8.)); %LET YYYYMM= %sysfunc(putn(%sysfunc(inputn(&GL_YMD,date9.)),yymmn6.));
内容的提问来源于stack exchange,提问作者HammerUser
相关产品推荐
相关产品推荐

