2009-02-18 154 views
4

我正在閱讀一些有不良日期的原始數據。具體來說,有人在非閏年鎖定「2月29日」。例如:SAS無效的「閏年」日期問題yymmdd8

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

客戶希望這個恢復到2月28日是否有這樣做的快速/有效的方法?例如相當於:

如果iserror(date)then date = date-1; ?

任何建議感激地收到!

回答

4

我會更仔細一點修復日期。這是一種方法。心連心。

%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. 
*/ 
3

這是來自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 ***/ 

有可能以某種方式將其合併到您的負載中。

+0

感謝AFHood - 我想此刻的不同的方法(已經發布了一個新的問題),但如果我無法擺脫導致我想我會用這個,而不是錯誤消息(把年變成一個宏變量)。好的一點代碼!謝謝.. – 2009-02-18 17:27:13

0

這不是很漂亮,有轉換筆記,但它的工作原理,並沒有錯誤。

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 
1

稍加修改上面的答案的版本(我認爲)。它避免了錯誤信息,但是「??」在輸入功能中。

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; 
+1

愛的??修改! – 2013-09-16 14:21:53