Is there a system option or similar that could be used to generate an ERROR whenever SAS relies on the value of the YEARCUTOFF option in order to interpret an ambiguous years?
Below illustrates how SAS uses YEARCUTOFF to interpret a two-digit year or one-digit year.
347 options yearcutoff=1800 ; 348 data _null_ ; 349 x1='7JUN2018'd ; 350 x2='7JUN18'd ; 351 x3='7JUN8'd ; 352 put x1= x2= x3= ; 353 format x1 x2 x3 date9. ; 354 run; x1=07JUN2018 x2=07JUN1818 x3=07JUN1808
I think I want something like YEARCUTOFF=ERROR, so that any time SAS tried to use the value of year cut off, it would return an error. This would be an offensive programming option, to say "I don't want my program to tolerate years with less than four digits."
I vaguely remember for Y2K the company I was at had some add-on (?) that would generate a NOTE or WARNING in the log whenever code had a two-digit year. But I don't think it was an official SAS product, and I don't remember how it worked.
If there's no good way to do this now, I'll submit it as a ballot item.
@Quentin wrote:
Thanks @ballardw. The concern is really the broad issue of how SAS handles a year value that has less than four digits. So would apply to date literals, informats, functions that create date values from text, etc etc. Generally I expect my code and data to have four-digit years. If it encounters a year with less than four digits (in any context), I'd like it to be an error.
Agree, I think setting yearcutoff to an unusual value is the best that could be done currently. But that forces you to add code to check each date value, which as you say is a hassle, and feels dangerous because you're intentionally risking creating invalid data that could be treated as valid. It's kind of like using -99 for missing values instead of special missing values.
Would be nice to have a way to say "Hey SAS, if you don't know what year a value represents, don't guess!" (To be more fair: "don't interpret the year according to the 100 year range specified in YEARCUTOFF").
Sounds like a Ballot option might be in order to see if you can get enough support.
I already have enough date checking such as "are people visiting the clinic before they are born" in my projects the yearcutoff isn't a major concern.
I'm not sure if this would help jog your memory, but you can certainly capture the YEARCUTOFF value using:
%let y = %sysfunc(getoption(yearcutoff));
Yeah, but it's not that I want to capture the value of YEARCUTOFF. I want a way to tell SAS that I don't want to use YEARCUTOFF to interpret ambiguous years. I want my session to expect four digit years from my code and data, and return an error if it finds a two digit year. So this would be for strict error handling, along the lines of varinitchk=error, varlenchk=error, or my favorite undocumented dsoptions=note2err.
Over time I've become a fan of offensive programming that errs on the side of throwing too many errors rather handling errors. This thought about YEARCUTOFF was prompted today because over on SAS-L it was pointed out that SAS date literals don't mind random text at the end, so SAS is happy to accept junk like:
1 data _null_ ; 2 x="07Jun1meh"d ; 3 put x date9.; 4 run ; 07JUN2001
Because it ignores the text at the end, and interprets the 1 as a one-digit year.
Is the concern here about date literals or Informat behavior? I suspect the data literal behavior is going to be somewhat different.
It is likely a PITA but you could do something like set the YEARCUTOFF to something extremely unlikely, such as 2200. Then any time dealing with the dates if the Year is > 2200 set an error message. Or perhaps a custom date range for "likely" date ranges.
options yearcutoff=2200; proc format library=work; value mydates '01JAN1960'D - '31DEC2030'd = [mmddyy10.] other = "_error_"; run; data junk; x='01Jan01'd; format x mydates.; run; options yearcutoff=1926;
You could test the result of the format to actually throw an error in a data step if desired.
Thanks @ballardw. The concern is really the broad issue of how SAS handles a year value that has less than four digits. So would apply to date literals, informats, functions that create date values from text, etc etc. Generally I expect my code and data to have four-digit years. If it encounters a year with less than four digits (in any context), I'd like it to be an error.
Agree, I think setting yearcutoff to an unusual value is the best that could be done currently. But that forces you to add code to check each date value, which as you say is a hassle, and feels dangerous because you're intentionally risking creating invalid data that could be treated as valid. It's kind of like using -99 for missing values instead of special missing values.
Would be nice to have a way to say "Hey SAS, if you don't know what year a value represents, don't guess!" (To be more fair: "don't interpret the year according to the 100 year range specified in YEARCUTOFF").
@Quentin wrote:
Thanks @ballardw. The concern is really the broad issue of how SAS handles a year value that has less than four digits. So would apply to date literals, informats, functions that create date values from text, etc etc. Generally I expect my code and data to have four-digit years. If it encounters a year with less than four digits (in any context), I'd like it to be an error.
Agree, I think setting yearcutoff to an unusual value is the best that could be done currently. But that forces you to add code to check each date value, which as you say is a hassle, and feels dangerous because you're intentionally risking creating invalid data that could be treated as valid. It's kind of like using -99 for missing values instead of special missing values.
Would be nice to have a way to say "Hey SAS, if you don't know what year a value represents, don't guess!" (To be more fair: "don't interpret the year according to the 100 year range specified in YEARCUTOFF").
Sounds like a Ballot option might be in order to see if you can get enough support.
I already have enough date checking such as "are people visiting the clinic before they are born" in my projects the yearcutoff isn't a major concern.
I added the ballot item:
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.