The SAS code in terms of "Date" - sas

I have encountered the code in terms of different ways in SAS to handle
"Date". However, I do not understand what the last "format" was doing here.
The code is as below.
DATA SASWEEK.Datestest;
INPUT d1 MMDDYY8. +1 d2 DATE9.;
* informat does;
* Can be replaced by an informat statement;
d1f = d1;
d2f= d2;
d3f = d2;
FORMAT d1f DATE9. d2f WORDDATE. d3f MMDDYY8.; *formats;
datalines;
01111960 12JAN1960
01011961 01MAR2013
;
PROC PRINt;
RUN;
PROC PRINT;
FORMAT d1f 9.0 d1 WEEKDATE.;
RUN;
Any suggestion and explanation would be highly appreciated!!

I'm not sure if you're referring to the format in the proc print as FORMAT d1f 9.0 d1 WEEKDATE.;, or the last format in the data step FORMAT d1f DATE9. d2f WORDDATE. d3f MMDDYY8.;.
Either way the format just affects the way data is displayed without changing the saved value, which in your case are just numeric as that is what dates are stored as.
SAS dates start from 0 as 1st January 1960, then 1 for 2nd January 1960, and so on. This is why values such as 10 and 11 can be seen in the proc print output in the first observation and the second observation follows the same counting sequence.
To reiterate, the format is just affecting the display, not the value.
Edit
In response to question in comment:
So based on your explanation, the last "d1f 9.0" was to make d1f from
01/11/60 -> "01111960"?
The short answer to your question is "no", an explanation is below.
The first observation for d1f is based on the input data 01111960 which is 11th January 1960, and so is day 10 as SAS counts days (as explained in my initial response).
Variable d1f contains the value 10 for the first observation.
d1f has the format DATE9. applied to it in the initial data step so the first proc print shows 11JAN1960 as the first value of d1f.
The second proc print has the format 9.0 applied to the value of d1f, this instructs SAS to display the value of d1f (value is 10) within 9 columns (with 0 decimal places), this is why you see 10 displayed as the first value of d1f in the second proc print.
The following data step might also help demonstrate what is happening if you run it after your code and check the log for the results:
data _null_;
set SASWEEK.Datestest;
put d1f;
put d1f 9.0;
put d1f 8.0;
put d1f 7.0;
put d1f 6.0;
put d1f 5.0;
put d1f 4.0;
put d1f 3.0;
run;

Related

How to calculate month number in sas

Hi I need to calculate the value of month supposed in sas
01jan1960 is equal to 1
02jan1960 is equal to 2
So I need to calculate for 01aug2020
I used intck function but no output
I want in datastep only .
SAS stores dates as the number of days since 1960 with zero representing first day of 1960. To represent a date in a program just use a quoted string followed by the letter D. The string needs to be something the DATE informat can interpret.
Let's run a little test.
6 data _null_;
7 do dt=0 to 3,"01-JAN-1960"d,'01AUG2020'd;
8 put dt= +1 dt date9.;
9 end;
10 run;
dt=0 01JAN1960
dt=1 02JAN1960
dt=2 03JAN1960
dt=3 04JAN1960
dt=0 01JAN1960
dt=22128 01AUG2020
So the date value for '01AUG2020'd is 22,128.
Subtraction works
days_interval = '01Aug2020'd - '01Jan1960'd;
Or looking at the unformatted value as SAS stores dates from 01Jan1960
days_interval = '01Aug2020'd;
format days_interval 8.;

Input date format YYYYMMDD

I need to input dates in YYYYMMDD format and create macro variables from these dates to use in a WHERE clause. The FINAL dataset should select one record from Sales but 0 observations are returned.
data work.FiscalYear2019;
input #1 fiscalYear $4. #5 StartDate mmddyy8.;
retain diff;
if fiscalYear = '2019' then do;
tday = today();
diff = tday - StartDate;
call symputx('FYTD_days',diff);
call symputx('CY_StartDate', StartDate);
call symputx('CY_EndDate', put(today(),mmddyy8.));
end;
else if fiscalYear = '2018' then do;
PY_EndDate = StartDate + diff;
call symput('PY_EndDate', put(PY_EndDate,mmddyy8.));
call symput('PY_StartDate', put(StartDate,mmddyy8.));
end;
datalines;
201912312018
201801012018
;
data work.Sales;
input #1 fiscalYear $4. #5 orderDate mmddyy8.;
format orderDate mmddyy6.;
datalines;
201902042019
201801012018
;
data final (WHERE=(orderDate >= &PY_StartDate AND
orderDate <= &PY_EndDate));
set Sales;
run;
I expect the FINAL dataset to contain one record from the Sales dataset but FINAL has 0 observations.
To use your macro variables as date values you need to either generate the macro variables as the raw number of days values, like you did with CY_StartDate, or generate them using the DATE format and enclose them in quotes and append the letter D to make a date literal.
Like this:
call symputX('PY_StartDate', put(StartDate,date9.));
call symputX('PY_EndDate', PY_EndDate);
...
data final
set Sales;
WHERE orderDate >= "&PY_StartDate"d
AND orderDate <= &PY_EndDate
;
run;
Also your subject line mentions YYYYMMDD informat and it does not appear in your code. Are you interpreting your source data properly? Does 201801012018 represent an 8 digit date in YMD order plus a four digit year? Or a four digit year plus an 8 digit date in MDY order?
You are just not referring to your macro variables in the last data step with the proper syntax. Those &PY_StartDate and &PY_EndDate variables are just strings after macro code is compiled, and you need to refer to them as date constants. So this should fix the issue:
data final (WHERE=(orderDate >= "&PY_StartDate"d AND
orderDate <= "&PY_EndDate"d));
set Sales;
run;
In the future, I recommend including options mprint; at the start of your code. This option displays the text generated by macro execution in your log, which can help greatly with debugging macros.

I would like to get Date and Time separately from DATETIME. format

I would like to get only date and time separately from 01JAN13:08:29:00
Format & Infomat available in Dataset is:
Date Num 8 DATETIME.(format) ANYDTDTM40(informat)
And If I run datepart() on 01JAN13:08:29:00 I get output as 19359 (I don't want it.)
The DATEPART function extracts the date value from a datetime value. The date value as you have seen is simply a number. A date format must be applied to a variable holding a date value. Base SAS variables have only two value types, character and numeric.
data want;
now_dtm = datetime();
now_dt = datepart(now_dtm);
now_dt_unformatted = now_dt;
format now_dtm datetime.;
format now_dt date9.; * <----- this is what you need, format stored in data set header information;
run;
proc print data=want;
run;
* you can change the format temporarily during a proc step;
proc print data=want;
format now_dt yymmdd10.; * <---- changes format for duration of proc step;
format now_dt_unformatted mmddyy10.;
run;
Actually 19,359 is exactly the value you want. You started with the number of seconds since 1960 and converted it to the number of days since 1960.
data x ;
dt = '01JAN13:08:29:00'dt ;
date = datepart(dt);
time = timepart(dt);
put (dt date time) (=);
run;
Results
dt=1672648140 date=19359 time=30540
You just need to attach a format to your new variable so that SAS will display the value in a format that humans will recognize. You could use a format like DATE9. to have it show 19,359 as 01JAN2013. Similarly you need to attach a format to the time part to make it print in format that human's will interpret as a time.
format date date9. time time8. ;

SAS, PROC FORMAT change string to numeric

I want to create a format on a string variable (Monday, Tuesday, Wednesd, Thrusda, Friday) to see the result as 1 to 5, so I can sort the data. I tried sth as:
proc format;
value days
'Monday'=1
'Tuesday'=2
'Wednesd'=3
'Thrusda'=4
'Friday'=5
run;
In the log file, an error likes this appear:
ERROR: The quoted string 'Monday' is not acceptable to a numeric format or informat.
ERROR 22-322: Syntax error, expecting one of the following: a quoted string, a format name.
ERROR 200-322: The symbol is not recognized and will be ignored.
Additional INFO
After creating the format, I will apply this in the plot, something like below:
PROC GLM data=Newspaper;
class Day Newspaper;
model ad_effect = Day|Newspaper;
**format Day days.;**
title 'Analyze the effects of Day & Newspaper';
title2 'Including Interaction';
run;
quit;
title;
Using the Format, the the marker in the scatter plot can be showed in a order from Monday to Friday. Otherwise, the marker will be showed based on alphabetical order.
Please share your idea.
You can use and INFORMAT to create a new variable by reading the day name as a number. For example.
proc format;
invalue days
'Monday'=1
'Tuesday'=2
'Wednesd'=3
'Thrusda'=4
'Friday'=5;
run;
data days;
input day:days.;
cards;
Monday
Tuesday
Wednesd
;;;;
run;
proc print;
run;

Date calculations in SAS

I want to add 1 day to an arbitrary SAS date. I have the following code that works but I wonder wether there is built-in support for date calculations like this:
proc fcmp outlib=whatever;
function lastDayInYear(d);
if datdif(d,mdy(12,31,year(d)),'ACT/365')=0 then return(1); else return(0);
endsub;
function advanceDate(d);
if d=. then return(.);
if lastDayInYear(d) then
return(mdy(1,1,year(d)+1));
else
return(datejul(juldate7(d)+1));
endsub;
quit;
Dates are just numbers, so to advance the day by one, you just, um, add 1.
Where did you find that code? Talk about using a sledgehammer to crack a nut...
Itzy is right... just add 1. If you want to do more advanced date calculations you can use the intnx() and intck() functions.
e.g.
data _null_;
tomorrow = date() + 1;
same_day_next_month = intnx('month',date(),1,'same');
first_day_next_week = intnx('week' ,date(),1,'beginning');
last_day_of_year = intnx('year' ,date(),0,'end');
put _all_;
run;
In SAS, there's no DATE or DATETIME data type, such values are stored as generic Numeric data type, where for date: the number stored represents number of days between date represented and January 1st 1960. For datetime it's similar, only number of seconds is stored. You'll see this in code below.
Human readable date, time and datetime representation is achieved via SAS date/time formats.
For further explanation just do a search on SAS dates on web and documentation.
Back to you're question: to add one day to a value representing DATE, just do a mathematical addition: +1.
data _null_;
length mydate mydatetime 8;
mydate='1jan1960'd;
mydatetime='1jan1960:00:00:00'dt;
nextdate = mydate + 1;
nextminute = mydatetime + 60;
put mydate 8. +4 mydate yymmdds10.;
put nextdate 8. +4 nextdate yymmdds10.;
put mydatetime 12. +4 mydatetime datetime.;
put nextminute 12. +4 nextminute datetime.;
run;