BookmarkSubscribeRSS Feed
VictorSirianni
Fluorite | Level 6

Hello,

 

I've been asked to measure workdays between event timestamps according to a variety of business rules. To accomplish this I am trying to create custom intervals that will allow me to measure from the start of the next workday to the end of the last workday and then subtract out non-workdays between them using INTNX & INTCK functions.

 

/*** concept ***/

first_workday_dt = intnx('workday',start_timestamp,+1,'beginning');
final_workday_dt = intnx('workday',stop_timestamp,-1,'end');

workday_minutes = intck('dtminutes',first_workday_dt,final_workday_dt) - (intck('non_workdays',first_workday_dt,final_workday_dt)*1440);

 

I have a dataset containing all dates for the current and previous three years with a flag indicating weekends and holidays. From this I've created two new datasets with begin and end times for workdays and non-workdays. Creating intervals from these allows me to perform the calculations described above, however, I am seeing null results when the input date is not in the interval dataset or incorrect results when the result would extend beyond the interval dataset. While this makes sense intuitively, I am at a loss as to how to fix or work around it.

 

Is what I am trying to do possible, and if so, how? I am also open to other approaches as well, we are just trying to find the most efficient and repeatable way to do this as it is a common ask. Thank you in advance!

 

Code:

/*** flag weekends and holidays ***/
data work.Calendar (keep=date flag); merge work.Days work.Holidays (in=holiday); by date;

  format Date date. Flag $10.;

  if weekday(date) in (1,7) then flag = 'Weekend';
    else if holiday = 1 then flag = type;
      else flag = '';

run;


/*** create sas interval datasets ***/
proc sql;
create table work.Calendar_Workdays as select dhms(date,00,00,00) as begin format = datetime., dhms(date,23,59,59) as end format = datetime. from work.Calendar where flag is missing;
create table work.Calendar_NonWorkdays as select dhms(date,00,00,00) as begin format = datetime., dhms(date,23,59,59) as end format = datetime. from work.Calendar where flag is not missing;
quit;

/*** create sas intervals ***/
options intervalds = (workday=work.calendar_workdays non_workday=work.calendar_nonworkdays);

/*** advance to next workday and back to previous workday ***/
data work.test; set work.days;
format next_business_day last_business_day datetime.;
  next_business_day = intnx('workday',dhms(date,12,00,00),+1,'beginning');
  last_business_day = intnx('workday',dhms(date,12,00,00),-1,'end');
run;

 

 

Results:

Capture.PNG

1 REPLY 1
mkeintz
PROC Star

Your calendar data sets have gaps, i.e. instances in which END for one observation is more than 1 unit (1 second) less than BEGIN for the next observation.

 

You could create END as next BEGIN-1 (much easier with a data step than in sql).  But you can also just drop the END variable.  Then sas will assume that end is just 1 less than the next begin, yielding no gaps.

 

 

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------

hackathon24-white-horiz.png

The 2025 SAS Hackathon has begun!

It's finally time to hack! Remember to visit the SAS Hacker's Hub regularly for news and updates.

Latest Updates

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 1 reply
  • 2423 views
  • 0 likes
  • 2 in conversation