Rewrite SAS code with condition based on dates - date

I have the following SAS code that I am trying to rewrite with condition. I am a SAS beginner and for now I can read and trying to learn code
DATA _NULL_;
date1=put(INTNX('day',&today,-1),DATE11.);
date2=put(INTNX('day',&today,-15),DATE11.);
call symput('rpt_dt',date1);
call symput('rpt_dt2',date2);
RUN;
instead of yesterday and two weeks ago, I would like the following condition:
date 1 = If the current date is greater than or equal to 1 and less than 16, set the date1 to the 16th of the previous month, otherwise set it to the 1st of the current month
date2 = If the current date is 16 and above, set the date2 to the 15th of the current month, otherwise set date2 to the last day of the previous month
I tried the following:
DATA _NULL_;
if day(today) between 1 and 15 then
date1 = put(intnx('month', &today, -1, 'e'),DATE11.);
else
date1 = put(intnx('month', &today, 0, 'b'),DATE11.);
if day(date1) = 1 then
date2 = put(intnx('day', &date1, 15, 'e'),DATE11.);
else
date2 = put(intnx('month', &date1, 0, 'e'),DATE11.);
call symput('rpt_dt',date1);
call symput('rpt_dt2',date2);
RUN;
DATA _NULL_;
if day(today) ge 1 and day(today) le 15 then
date1=put(intnx('month',today,-1,'E'), date11.);
date2=put(intnx('month',today,-1,'L'), date11.);
else
date1=put(intnx('month',today,0,'B'), date11.);
date2=put(intnx('month',today,0,'L'), date11.);
call symput('rpt_dt',date1);
call symput('rpt_dt2',date2);
RUN;
but each one was not successful and I get error in the between, the do, or missing then.

Since SAS has a different syntax, the if-then should be explicit.
DATA _NULL_;
if day(today) ge 1 and day(today) le 15 then
date1=put(intnx('month',today,-1,'E'), date11.);
date2=put(intnx('month',today,-1,'L'), date11.);
if day(today) > 15 then
date1=put(intnx('month',today,0,'B'), date11.);
date2=put(intnx('month',today,0,'L'), date11.);
call symput('rpt_dt',date1);
call symput('rpt_dt2',date2);
RUN;

Related

intck() giving negative value

I am new to SAS and I am having trouble with finding the difference between 2 dates.
I have 2 columns: checkin_date and checkout_date
the dates are in mmddyy10. format (mm/dd/yyyy).
I have used the following code:
stay_days= intck('day', checkin_day, checkout_day);
I am getting the right values for dates in the same month but wrong values for days that are across 2 months. For example, the difference between 02/06/2014 and 02/11/2014 is 5. But the difference between 1/31/2014 and 2/13/2014 is -18 which is incorrect.
I have also simply tried to subtract them both:
stay_day = checkout_day - checkin_day;
I am getting the same result for that too.
My entire code:
data hotel;
infile "XXXX\Hotel.dat";
input room_no num_guests checkin_month checkin_day checkin_year checkout_month checkout_day checkout_year internet_used $ days_used room_type $16. room_rate;
checkin_date = mdy(checkin_month,checkin_day,checkin_year);
informat checkin_date mmddyy.;
format checkin_date mmddyy10.;
checkout_date = mdy(checkout_month,checkout_day,checkout_year);
informat checkout_date mmddyy.;
format checkout_date mmddyy10.;
stay_day= intck('day', checkin_day, checkout_day);
Your problem is a typo - using wrong variables in intck() function. You are using variables "xxx_DAY" which is the DAY of month instead of the full DATE. Change to stay_day= intck('day', checkin_date, checkout_date);
Your data probably has the date values in the wrong variables. When using subtraction the order should be ENDDATE - STARTDATE. When using INTNX() function the order should be from STARTDATE to ENDDATE. In either case if the value in the STARTDATE variable is AFTER the value in the ENDDATE variable then the difference will be a negative number.
Perhaps you need to clean the data?
The only way to get -18 comparing 2014-01-31 and 2014-02-13 would be if you extracted the day of the month and subtracted them.
diff3 = day(end) - day(start);
which would be the same as subtracting 31 from 13.
Example using your dates:
data check;
input start end ;
informat start end mmddyy.;
format start end yymmdd10.;
diff1=intck('day',start,end);
diff2=end-start;
cards;
02/06/2014 02/11/2014
1/31/2014 2/13/2014
;
Results:
Obs start end diff1 diff2
1 2014-02-06 2014-02-11 5 5
2 2014-01-31 2014-02-13 13 13

How to get all the yyyymm dates between two dates which are in yyyymm format in SAS?

I have two different dates 201509 and 201608. I want to get all the dates between them in the format yyyymm like (201509,201510,201511,201512,201601,201602,201603,201604,201605,201606,201607,201608). The issue is tackling the months between years. ALso, teh months keep changing and it might be just 201601 to 201612. It's a daily run code and I'm trying to automate it in SAS. Any help appreciated!
SAS has functions that allow you to do this easily but you must first convert/read your dates as "SAS Dates". Then you can use INTCK to count the months between start and end and INTNX to create the new month date values.
data months;
input (start end)(:yymmn.);
format start end yymm.;
do i = 0 to intck('month',start,end);
month = intnx('month',start,i);
output;
end;
format month yymm.;
cards;
201509 201608
;;;;
run;
proc print;
run;
If they're date format already then add a day onto the interval and it can be as simple as
where date between '01Jan2016'd and '31Dec2016'd;
If you can't figure out the logic each day, you can create macro variables that will do it for you.
%let start=201601;
%let end=201612;
%let start_date = %sysfunc(inputn(&start, yymmn6.), date9.);
%let end_date = %sysfunc(intnx(month, %sysfunc(inputn(&end, yymmn6.)), 0, end), date9.);
%put &start_date.;
%put &end_date;
Logic is below.
For intY = intStartYear To intEndYear
If intY = Value(intEndYear) Then intZ = Value(intEndMonth) Else intZ = 12
For intX = intStartMonth To intZ
If intX < 10 Then
Print intY & "0" & intX
Else
Print intY & intX
End If
Next intX
intStartMonth = 1
Next intY

SAS date swap year and day

I am working with a dataset containing a date variable with the format MMDDYY10..
The problem is, that the day, month and the year have been swapped.
The data set as it looks now:
Obs Date
1 11/01/1931
2 11/06/1930
3 12/02/2003
4 12/07/2018
What I would like is a date variable with the format DDMMYY10., or a similar:
Obs Date
1 31/01/2011
2 30/06/2011
3 03/02/2012
4 18/07/2012
Observation 1 is hence written as the 1st of November 1931, but really it is the 31st of January 2011.
Does anyone know how I can change this?
Looks like you read the original raw data using the wrong INFORMAT. Most likely you had data in YYMMDD format and you read it as MMDDYY. You can use the PUT() and INPUT() functions to attempt to reverse it.
data have ;
input date mmddyy10.;
newdate = input(put(date,mmddyy6.),yymmdd6.);
format date newdate yymmdd10. ;
put (date newdate) (=);
cards;
11/01/1931
11/06/1930
12/02/2003
12/07/2018
;;;;
Results:
date=1931-11-01 newdate=2011-01-31
date=1930-11-06 newdate=2011-06-30
date=2003-12-02 newdate=2012-02-03
date=2018-12-07 newdate=2012-07-18

Better way to make/compare date ranges?

I often have data that has a date1 and a date2. Date1 is the date we guess will have the event and date2 an event. I usually need to make 2 dummy variables where I increment date1 forwards a week and backwards then compare with the other 2. However I keep thinking there must be a better way to create a date range and then compare with a second date!
Is there a way to do this in sas? Basically I want to take date1 and date2 and make this dataset and am wondering if I MUST create 2 additional variables (date1-7 days and date1+7days)
Input datset:
DATE1 DATE2
10/23/2014 2/12/2015
2/12/2015 2/10/2015
Current output:
DATE1_wk_before Date1_wk_after Date2 In_range_indicator
10/16/2014 10/30/2014 2/12/2015 0
2/05/2015 2/19/2015 2/10/2015 1
Where In_range_indicator = 1 if date is in the range and 0 if not in the range
I want to know if I can do it just where I do something like
In_range_indicator= 1 where Date2 is in range(week before date1 , week after date1) without creating 2 extra sets of data. It seems a waste of time.
I am LITERALLY adding 7 days and subtracting 7 days before and after and it seems a bad way to do this.
You seems to just want to set the value of a variable based on a condition. No need to get too clever with it, just if and else in your data step:
if date2 ge date1-7 and date2 le date1+7 then ind=1;
else ind=0;
Agree with #DWal, simple if and else statement can help. You can also use IFN function.
data mydates;
infile datalines missover;
input (date1-date2) (:mmddyy10.);
In_range_indicator=ifn( date1-7 <= date2 <= date1+7 , 1,0);
format date1-date2 yymmdd10.;
datalines4;
10/23/2014 2/12/2015
2/12/2015 2/10/2015
;;;;
run;
proc print data=mydates;run;
if abs(date2-date1)<7 then ind=1; else ind=0;

Finding last Sunday and going 4 weeks backward every week in SAS

I have a SAS job that runs every Thursday, but sometime it need to run on Wednesday, and maybe Tuesday evening. The job collects some data in 4 week intervals up until the closest Sunday. For example, today we have 19Mar2015, and I need data until 15Mar2015.
data get_some_data;
set all_the_data;
where date >= '16Feb2015' and date <= '15Mar2015';
run;
Next week I have to manually change the date parameters too
data get_some_data;
set all_the_data;
where date >= '23Feb2015' and date <= '22Mar2015';
run;
Anyway I can automate this?
I'll expand on the suggestion from #user667489 as it could take you a while to work it out. The key is to use the week time interval, which by default starts on a Sunday (you can change this with a shift index, read this for further details)
So your query just needs to be :
where intnx('week',today(),-4)<date<=intnx('week',today(),0);
Use the INTNX function to regress the date back to last Sunday:
data get_some_data;
set all_the_data;
lastsun=intnx('week',today(),0);
/*where date >= '23Feb2015' and date <= '22Mar2015';*/
where date between lastsun-27 and lastsun;
run;
You can try getting the last sunday date using weekday function and then using INTNX get the 4 week back date from that sunday date. Check the below ref code :
data mydata;
input input_date YYMMDD10.;
/* Loop to get the last sunday date, do the processing
and get out of loop */
do i =0 to 7 until(last_sunday_date>0);
/* Weekday Sunday=1 */
if weekday(sum(input_date,-i))=1 then do;
last_sunday_date=sum(input_date,-i);
/* INTNX to get the 4 week back date */
my_4_week_start=intnx('week',last_sunday_date,-4);
end;
end;
format input_date last_sunday_date my_4_week_start yymmdd10.;
datalines4;
2015-03-01
2015-03-07
2015-03-14
2015-03-21
2015-03-28
2015-04-05
2015-04-13
2015-04-20
;;;;
run;
proc print data=mydata;run;
let me know if this helps!