【问题标题】:SAS invalid 'leap year' date issue yymmdd8SAS 无效的“闰年”日期问题 yymmdd8
【发布时间】:2010-10-08 08:41:48
【问题描述】:

我正在阅读一些包含几个错误日期的原始数据。具体来说,有人在非闰年键入“2 月 29 日”。例如:

data _null_;
input test :yymmdd8.;
format test date9.;
cards;
20270229
run;

客户希望恢复到 2 月 28 日。是否有快速/有效的方法来执行此操作?例如相当于:

IF iserror(date) 然后 date=date-1; ?

任何建议都非常感谢!

【问题讨论】:

    标签: date sas


    【解决方案1】:

    这是来自 SCONSIG 的一个很好的提示。 link

    /******************************************************************/
     /***TIP00039.SAS                                                ***/
     /***   Leap Year Problem                                        ***/
     /***                                                            ***/
     /***   Most of us know that if the year is divisible by 4 then  ***/
     /***   that year is a Leap Year.  However, if the year is a     ***/
     /***   century year and is NOT divisible by 400 then that       ***/
     /***   century year is NOT A LEAP YEAR.                         ***/
     /***   (ie, 1700, 1800, 1900, 2100, 2200, 2300 are not LEAP     ***/
     /***        YEARS)                                              ***/
     /***                                                            ***/
     /******************************************************************/
    
     data leapyear;
       do year = 1600 to 2400 by 100;
        date = mdy(02,29,year);        /*** Leap Date                       ***/
        if date = . then do;           /*** If FEB 29th but not a Leap Year ***/
           date = mdy(03,01,year) - 1; /*** Make date March 1st and then    ***/
        end;                           /***   subtract 1 day                ***/
        output;
       end;
       format date mmddyy10.;
     run;
    
     proc print; run;
    
     /*** end of sas program - TIP00039 ***/
    

    可以以一种或另一种方式将其合并到您的负载中。

    【讨论】:

    • 谢谢 AFHood - 我目前正在尝试一种不同的方法(已经发布了一个新问题),但如果我无法摆脱导致错误消息的结果,我想我会改用它(把年转化为宏变量)。代码不错!谢谢..
    【解决方案2】:

    这不漂亮,有转换说明,但它有效且不会出错。

    data testit;
       format test2 yymmdd10.;
       input x $8.;
       mod4 = mod(mod((substr(x,1,4)/4),4) * 10,10);   
       if mod4 NE 0 then x = x - 1;
       test2=input(x,yymmdd8.);
       put x= test2=;
    
    cards;
    20080229
    20090229
    20100229
    20110229
    20120229
    20130229
    20270229
    run; 
    

    输出:

    x=20080229 test2=2008-02-29
    x=20090228 test2=2009-02-28
    x=20100228 test2=2010-02-28
    x=20110228 test2=2011-02-28
    x=20120229 test2=2012-02-29
    x=20130228 test2=2013-02-28
    x=20270228 test2=2027-02-28
    

    【讨论】:

      【解决方案3】:

      上述答案的略微修改版本(我认为)。它通过“??”避免了错误消息在输入函数中。

      data testit;
         format indate yymmdd10.;
         input x $8.;
      
         indate = input(x, ?? yymmdd8.);
         if indate=. then indate= input(put(x - 1, 8.), ?? yymmdd8.);
      
      
          put indate=;
      
      cards;
      20080229
      20090229
      20100229
      20110229
      20120229
      20130229
      20270229
      run;
      

      【讨论】:

      • 喜欢 ??修饰符!
      【解决方案4】:

      我会更加小心地确定日期。这是一种方法。 hth。

      %put sysvlong=&sysvlong sysscpl=&sysscpl;           
      /* sysvlong=9.02.01M0P020508 sysscpl=W32_VSPRO */
      
      /* read a date both as character(temp) and numeric(date).
         if the numeric date is missing then check if the
         character date ends with "0229," if so, then change it
         to "0228" and see if it is a valid date. 
         If OK, then that is it. otherwise, keep it missing. */
      %let FEB29 = 0229; 
      %let FEB28 = 0228;
      data one;
        drop temp;
        input temp $char8. @1 date ?? yymmdd8.;
        if missing(date) then link fix;
        format date b8601da.;
        put (_all_) (=);
        return;
      fix:
        if length(strip(temp))^=8 then return;
        if substr(temp,5) ^= "&FEB29" then return;
        date = input(cat(substr(temp,1,4), "&FEB28"), ?? yymmdd8.);
      return;
      cards;
      20080229  ok
      20090229  should be changed to 28th
      201XX229  this should be missing
      20110229  -> 28
      20120229  ok 
      20130229  -> 28
      20270229  -> 28
      ;
      run;
      
      /* on log
      temp=20080229 date=20080229
      temp=20090229 date=20090228
      temp=201XX229 date=.
      temp=20110229 date=20110228
      temp=20120229 date=20120229
      temp=20130229 date=20130228
      temp=20270229 date=20270228
      NOTE: The data set WORK.ONE has 7 observations and 1 variables.
      */
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-14
        • 2016-06-12
        相关资源
        最近更新 更多