【问题标题】:Convert character variable in unknown date/datetime format to numeric date将未知日期/日期时间格式的字符变量转换为数字日期
【发布时间】:2014-12-22 12:46:43
【问题描述】:

我有大约 30 个数据集,每个数据集大约有 20 个日期字段,其中变量类型在字符和数字以及日期和日期时间格式之间变化,即以下情况...

a.) 数字 - 日期 b.) 数字 - 日期时间 c.) 字符 - 日期 d.) 字符 - 日期时间

我想将每个单独的字段转换为数字和 date9。格式。我尝试编写下面的宏,当变量是字符串时,它不会产生正确的结果。出了什么问题? ...如果未正确指定字符变量 dateformat,则 sas 似乎无法正确解释输入语句。

%macro converttodate(inlib,indata,outlib,outdata,invar,outvar);

ods listing close;
ods output dataset.variables = work.formats;
proc contents data = &inlib..&indata.;
run;
data work.formats;
    set work.formats;
    where lowcase(compress(variable)) = lowcase(compress("&invar."));
run;
data _NULL_;    
    set work.formats;
    call symput('dtype',compress(lowcase(type)));
    call symput('dformat',compress(lowcase(format)));
    call symput('dlen',compress(put(len,8.)));
run;
%PUT INVAR  = ** &invar. ** OUTVAR = ** &outvar. **;
%PUT TYPE   = ** &dtype. **;
%PUT FORMAT = ** &dformat. **;
%PUT LENGTH = ** &dlen. **;

%if &dtype. = num %then %do;

    data &outlib..&outdata.;
        length tmp_put $50; 
        set &inlib..&indata.;
        format &outvar. date9.;
        tmp_put = compress(put(&invar.,&dformat.));
        if index(tmp_put,':') > 0 then &outvar. = datepart(&invar.); 
        else &outvar. = &invar.;
        drop tmp_put;
    run;

%end;
%else %do;

    data &outlib..&outdata.;
        set &inlib..&indata.;
        format &outvar. date9.;
        if index(&invar.,':') > 0 then &outvar. = datepart(input(&invar.,datetime.)); 
        else &outvar. = input(&invar.,date.);
    run;

%end;

%mend;

例如

data work.test;
    format x1 date9. y1 datetime30.6;
    x1 = mdy(10,16,1922);
    x2 = put(x1,date9.);
    y1 = 100000;
    y2 = put(y1,datetime30.6);
run;


%converttodate(
    inlib   = work,
    indata  = test,
    outlib  = work,
    outdata = test,
    invar   = x2,
    outvar  = x2_out);

【问题讨论】:

  • 如果你运行上面的代码,x2_out 会变成 '16OCT2019' 而不是 '16OCT1922'。

标签: date datetime sas


【解决方案1】:

宏中的这一行导致了意外行为:

else &outvar. = input(&invar.,date.);

日期的默认长度。是 7,所以它读取日期为 16OCT19,即 2019 年

http://support.sas.com/documentation/cdl/en/etsug/60372/HTML/default/viewer.htm#etsug_intervals_sect008.htm

如果你把它改成 date9 就可以了。如果要更改整个宏,可以查看 inputn 函数,其中函数的第二个参数可以由输入数据的长度动态确定。

data &outlib..&outdata.;
    set &inlib..&indata.;
    format &outvar. date9.;

    in_format=catt("date", &dlen.);

    if index(&invar.,':') > 0 then &outvar. = datepart(input(&invar.,datetime.)); 

    else &outvar. = inputn(&invar.,in_format);

run;

【讨论】:

    【解决方案2】:

    如果我在输入语句中使用正确长度的字符串,则输出变量似乎变得正确。我在 %else %do; 之后调整了代码如下

    %else %do;
    
        data _NULL_;
            set &inlib..&indata.;
            if length(compress(&invar.)) > 1 then do;
                call symput('dlen2',compress(put(length(compress(&invar.)),8.)));
                call symput('colon',compress(put((index(&invar.,':') > 0),8.)));
                stop;
            end;
            else do;
                call symput('dlen2','0');
            end;
        run;
        %if &dlen2. ^= 0 %then %do;
            data &outlib..&outdata.;
                set &inlib..&indata.;
                format &outvar. date9.;
                %if &colon. = 1 %then %do;
                    &outvar. = datepart(input(&invar.,datetime&dlen2..)); 
                %end;
                %else %do;
                    &outvar. = input(&invar.,date&dlen2..);
                %end;
            run;
        %end;
        %else %do;
            %PUT NO VALID OBSERVATIONS;
        %end;
    
    %end;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-13
      • 2013-12-28
      • 1970-01-01
      • 2022-08-18
      相关资源
      最近更新 更多