Selecting first of month sas dates - date

I have a sasdataset with a number of observations where one of the variables is called DATO.
This variable contains the Date that the observation was added to the dataset.
Previously i have used the following:
WHERE (DATE() - DATO) < 250;
To select which Observations to print, but this comes with issues. Previously i added observations monthly, but now i do it on daily basis.
I need to find a way to print out only observations which are from the first day of the last 8 months.
I can probably figure out the issue with the 8 months, but not how to select only the first day of the month. Any help would be greatly appreciated.

data _null_;
infile cards;
input DATO:date9.;
if day(DATO)=1 /* first of the month */
and DATO>intnx('MONTH',date(),-8) /* returns date shifted back 8 months */
then put DATO= date9.;
cards;
01JAN2013
02JAN2013
01FEB2013
01MAR2013
03MAR2013
;run;
results:
DATO=01JAN2013
DATO=01FEB2013
DATO=01MAR2013

Related

Automating weekday function for multiple dates with different permutations

I need to apply a certain treatment to sas dates depending on what day of the month the 1st of the month falls on. I need this to go forward for a number of months.
I’ve created the following as I also need macro variables for the start and end dates of the month.
%let first_dt = '01Jun2020'd;
data _null_
do j =0 to 12;
call Symputx(cats("&monstrt",j),put(intnx("month","first_dt",j,"b"),date9.),'g');
call Symputx(cats("&monend",j),put(intnx("month","first_dt",j,"e"),date9.),'g');
end;
run;
I now need to based on the 12 start of the month dates I have, increment the number of days. E.g. if start of month is a Monday I need to increment by 5 days, I’d start of the month is a Tuesday I need to increment by 6 days and so on.
I have attempted the following but it doesn’t appear to be working.
%macro weekdays(weekday);
data test;
if weekday("strt&i."d) = &weekday. then
new_stdt = put(intnx('day',"strt&i."d,+5),date9.)
;
%mend;
%weekdays(1,2,3,4,5,6,7);
Essentially I’m hoping to get all these dates to become populated based off the first_st variable, if this then subsequently changed, I could amend the original value and new values would be populated off of the back of that.
Here is a method that allows you to specify the values the add as a list of 7 numbers. For example this list matches the values in your comment.
%let add=11 5 6 7 8 9 10;
Notice how Monday and Tuesday are mapped to the 5 and 6 you mentioned in your question.
So if you have these values:
%let first_dt = '01Jun2020'd;
%let offset= 8 ;
You can generate a new date value like:
%let date = %sysfunc(intnx(month,&first_dt,&offset,b));
%let date = %eval(&date + %scan(&add,%sysfunc(weekday(&date))));
If you need to have the value of DATE look like something a human would understand you could add.
%let date = "%sysfunc(putn(&date,date9.))"d ;
So when the month offset is 8 the first of the month is on a Monday so the resulting date is 5 days after the first of the month.
1168 %put &=date;
DATE="06FEB2021"d

How can I count the number of weekdays between two dates, considering Saturday a weekday?

I have a dataset with the first and the last day of an event. I need to calculate the number of weekdays between the two dates. However, I need to consider Saturday as a weekday. How can I do that?
This is the example which is exactly like my dataset, but smaller. I've been using it to test the code before running everything:
data testing_weekdays;
input id $ date_1 date9. id2 $ dat2_2 date9.;
format date_1 date9. dat2_2 date9.;
datalines;
AA 01jan2019 AA 25jan2019
BB 02feb2019 BB 12feb2019
CC 10aug1990 CC 05jan1995
DD 11dec1999 DD 21dec1999
;
run;
When I use the intck function with the parameter 'weekday', I get the difference considering both Saturday and Sunday as weekend. But I would like to consider only Sunday.
I saw this solution on SAS community: https://communities.sas.com/t5/SAS-Programming/Sunday-to-Saturday-work-day/td-p/338412, but I can't make it work.
You can use sas function intck to find required interval. in your example, following will be the statement:
data want;
set testing_weekdays;
wkdays=intck('WEEKDAY1W',date_1,dat2_2);
run;
You can use different formats for Weekday interval. The days are numbered as Sunday(1) .. Saturday(7). So if you want to keep Sunday as a weekend, then WEEKDAY1W is used as interval.. Say if you want Monday(2), Wed(4) as weekends, then use- WEEKDAY24W
data new;
set old
interval=intck('weekday1w',begin,end);
run;

Marking full weeks inside a month including remaining days from other months

I have a dataset with daily data. I need to create a variable which brings the number of the week in each month (1 to (4 or 5)).
I have reached that with the following formula:
WK_NUM = intck('week',intnx('month',DATE,0),DATE)+1;
It works fine, but frequently the first and the last weeks of the month aren't full weeks, so the line only brings partial weeks. I need to improve it to bring remaining days from previous or next month in order to fill each week with 7 days.
Any ideas?
Hope this creates the expected result:
/* initial data set with dates */
data a;
format date date9.;
do date="15apr2017"d to "15jun2017"d;
output;
end;
run;
/* adding week number */
data a;
set a;
wk_num = week(date,'u');
run;
/* selecting May and modifying wk_num */
proc sql noprint;
CREATE TABLE b AS
SELECT date
,wk_num - ((SELECT min(wk_num) FROM a WHERE date="01may2017"d)-1)
FROM a
WHERE wk_num between (SELECT min(wk_num) FROM a WHERE date="01may2017"d) AND (SELECT max(wk_num) FROM a WHERE date="31may2017"d)
;
quit;
Option for week function:
u (default): specifies the number-of-the-week within the year. Sunday is considered the first day of the week. The number-of-the-week value is represented as a decimal number in the range 0-53. Week 53 has no special meaning. The value of week('31dec2006'd, 'u') is 53.
v: specifies the number-of-the-week whose value is represented as a decimal number in the range 1-53. Monday is considered the first day of the week and week 1 of the year is the week that includes both January 4th and the first Thursday of the year. If the first Monday of January is the 2nd, 3rd, or 4th, the preceding days are part of the last week of the preceding year.
w: specifies the number-of-the-week within the year. Monday is considered the first day of the week. The number-of-the-week value is represented as a decimal number in the range 0-53. Week 53 has no special meaning. The value of week('31dec2006'd, 'w') is 53.

SAS: create time ID variable with program (instead of using the point-and-click system)

SAS offers a point-and-click system to create a time ID variable from a certain starting date using a particular frequency (e.g. weeks, quarters, years).
Since I need to do this proces repeatedly, I like to use a code as it makes things much easier. My data covers 1985-2005 and is divided into quarters (which gives 21 years * 4 quarters = 84 observations).
The date variable column should look like this (or give any other sas date which can be formated):
Date:
1985/1
1985/2
1985/3
1985/4
1986/1
etc.
Does anyone knows how to write a code for this?
Thank you very much in advance!
Rens (a PhD student in sociology working on the music charts)
You can use a data step and the YYQ function.
data quarters;
do year = 1985 to 2005;
do quarter = 1 to 4;
date = yyq(year,quarter);
output;
end;
end;
format date yyq.;
run;
proc print;
run;
Use intnx function.
data have;
do i=0 by 1;
date=intnx('quarter',yyq(1985,1),i);
if date>yyq(2005,4) then return;
output;
end;
format date yyqs6.;
run;

SAS - determining time periods of medication use as well as time periods of no medication use

I am workin with prescription claims data. Subject X has 20 rows showing the dates he filled his prescriptions. Upto observation 5 he fills his prescription monthly. This is time bloc 1. The next observation has a fill date of 2 years later and has monthly fills for the next 15 rows. This is time bloc 2.
Question: How can I calculate the time on medication for each time bloc? I do not want to include the 2 year time frame that subject x is not filling his prescription.
It can be done in two steps: first, we "mark down" blocks; then group them.
Your dataset should be presorted bu subject and date (ascending).
data have2;
set have;
by Subject;
if Date-lag(Date)>30 then Block+1;
if FIRST.Subject then Block=1;
run;
proc sql;
create table blocks as
select Subject, Block, max(Date)-min(Date) as Duration
from have2
group by Subject, Block;
quit;