BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
primmer300174
Fluorite | Level 6

Apologies if this is already been posted, I'm new to this. I'm trying to get 30 min interval data or to the end time for Agent activity for work. the code I have is :-

 

data test;
set schedule2;
format Mystart MyEnd tod8.;
do Mystart = Start to Stop by 1800;
MyEnd = MyStart + 1800;

output;
end;

run;

 

This works for the most part, but it's not working if the interval end time is like 16:45:00. This is what I have :-

02-Jun-25Sick09:00:0016:45:0046516:00:0016:30:00
02-Jun-25Sick09:00:0016:45:0046516:30:0017:00:00
02-Jun-25Meal16:45:0017:15:003016:45:0017:15:00
02-Jun-25Meal16:45:0017:15:003017:15:0017:45:00

But what I want is :-

02-Jun-25Sick09:00:0016:45:0046516:00:0016:30:00
02-Jun-25Sick09:00:0016:45:0046516:30:0016:45:00
02-Jun-25Meal16:45:0017:15:003016:45:0017:00:00
02-Jun-25Meal16:45:0017:15:003017:00:00

17:15:00

I know I am missing something but I cannot figure it out. Can someone please assist.

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

Using the MINUTE30 interval should work.

data want;
  set have;
  do interval=0 to intck('minute30',start,stop);
    MyStart=max(start,intnx('minute30',start,interval,'b'));
    MyEnd=min(stop,intnx('minute30',start,interval+1,'b'));
    output;
  end;
  format mystart myend tod8.;
run;

Result

Screenshot 2025-06-15 at 4.56.54 PM.png

View solution in original post

16 REPLIES 16
PaigeMiller
Diamond | Level 26

Please explain further. You say you want 30 minutes intervals, but in the bottom table (which is what you want to get) you have mostly 15 minute intervals.

 

Also, we would need to see a portion of the starting data, which you have not shown us. (In other words, we need to see a portion of data set SCHEDULE2)

--
Paige Miller
primmer300174
Fluorite | Level 6

The ask of me is to have interval data per agent for productivity. but if the interval ends at 16:45:00, that would be classed as 0.5 for that interval as they are not productive for the whole 30 min interval. Hope this clarifies what I have asked for

PaigeMiller
Diamond | Level 26

@primmer300174 wrote:

The ask of me is to have interval data per agent for productivity. but if the interval ends at 16:45:00, that would be classed as 0.5 for that interval as they are not productive for the whole 30 min interval. Hope this clarifies what I have asked for


So, please explain why your desired data is a 30 minute interval for record 1, but 15 minute intervals for records 2 through 4. Also, please SHOW us a portion of the input data in data set SCHEDULE2.

--
Paige Miller
LinusH
Tourmaline | Level 20

Apart from @PaigeMillers input, I don't understand why you have a do loop, since you're doing OUTPUT outside of the loop?

Data never sleeps
primmer300174
Fluorite | Level 6

I'm doing a loop and output so that it gives every iteration for the 30 mins interval I'm requiring

Tom
Super User Tom
Super User

First point is it will be easier for everyone (you included) if you provide the example data as a SAS data step.  And keep it small enough to demonstrate the issue.

From your listing it looks like you started with two observations. But lets use a shorter time range for the first one.

data have;
  input date :date. meal :$10. start :time. stop :time. value;
  format date yymmdd10. start stop tod8.;
cards;
02-Jun-25 Sick 09:00:00 10:45:00 465 
02-Jun-25 Meal 16:45:00 17:15:00 30 
;

Second if you want the last interval to be capped at the STOP time then use the MIN() function.

Third if don't want an extra interval that STARTS at the STOP time then add more logic to prevent that.  You might try subtracting a fraction of a second from the upper bound used in the DO loop.

data want;
  set have ;
  length interval Mystart MyEnd 8;
  do Mystart = Start to Stop-0.01 by '00:30:00't;
    interval=sum(interval,1);
    MyEnd = min(MyStart + '00:30:00't,stop);
    output;
  end;
  format Mystart MyEnd tod8.;
run;

Note: Try to avoid using "magic" numbers in your code.  How is the next programmer that works on this program supposed to know why you used the number 1,800?

Tom_0-1749820847739.png

 

primmer300174
Fluorite | Level 6

Firstly, thank you for your advise, noted and will amend current and future codes to prevent the "magic" numbers etc. Makes sense to me but like you said, anyone else looking at it may not understand.

 

This is almost what I need. for row 5, where it says MyEnd at 17:15:00, think need to be 17:00:00 and then an additional to say MyStart 17:00:00 and MyEnd to say 17:15:00

Tom
Super User Tom
Super User

@primmer300174 wrote:

Firstly, thank you for your advise, noted and will amend current and future codes to prevent the "magic" numbers etc. Makes sense to me but like you said, anyone else looking at it may not understand.

 

This is almost what I need. for row 5, where it says MyEnd at 17:15:00, think need to be 17:00:00 and then an additional to say MyStart 17:00:00 and MyEnd to say 17:15:00


As @PaigeMiller said why do you want to switch from 30 minutes intervals to 15 minute intervals on that second subject?  How can the program know to treat that subject differently?

primmer300174
Fluorite | Level 6

I have to convert each duration into 30 minute intervals for comparing against the scheduled activity which is in 30 minute intervals. 

This is what the Resource planning area have given me and will not change this. I am trying to work out how many agents I would have (whether fully or partly) in that 30 minute interval. I have examples where a break has been place at 10:55:00 - 11:05:00 which would mean I need to have the MyStart as 10:55:00 - MyEnd 11:05:00 and then an additional row that would say MyStart as 11:05:00 and MyEnd as 11:30:00.

Hope this make sense and clarifies the confusion.

 

Quentin
Super User

This is still confusing, as you've introduced a new concept of a 'break'.  Please provide an example of the sample data you HAVE (schedule2), and the output you WANT from that sample data.   As a DATA step with CARDS statement, as Tom showed, and Paige asked for at the beginning of this thread.

The Boston Area SAS Users Group is hosting free webinars!
Next up: Lisa Mendez & Richann Watson present Get Tipsy with Debugging Tips for SAS® Code: The After Party on Wednesday Jul 16.
Register now at https://www.basug.org/events.
Tom
Super User Tom
Super User

So you want to merge a series of 30 minutes intervals with your existing time period.

 

You could do something like this to calculate the intervals for each subject separately.

data want;
  retain window '00:30:00't;
  set have ;
  length interval Mystart MyEnd 8;
  base_time = window*int(start/window);
  do interval=1 by 1 until(MyEnd >= Stop);
    myend = base_time + interval*window;
    mystart = myend-window;
    output;
  end;
  format Mystart MyEnd tod8.;
  drop window base_time;
run;

Tom_0-1749834091702.png

Or you could generate all of the intervals in a 24 hour day and join the two datasets using PROC SQL.

data intervals;
  do mystart=0 to '24:00:00't by '00:30:00't ;
    myend=mystart + '00:30:00't;
    output;
  end;
  format mystart myend tod8.;
run;

proc sql;
create table want as 
select a.*,b.*
from have a
  left join intervals b
  on a.start < b.myend
  and a.stop > b.mystart
order by a.date,b.mystart,b.myend
;
quit;

Tom_1-1749834426281.png

You might want to add more logic if you want the MYstart and MYend times not extend beyond the start and stop times.

proc sql;
create table want as 
select a.*
     , max(a.start,b.mystart) as MyStart format=tod8.
     , min(a.stop,b.myend) as MyEnd format=tod8.
from have a
  left join intervals b
  on a.start < b.myend
  and a.stop > b.mystart
order by a.date,b.mystart,b.myend
;
quit;

Tom_0-1749834961033.png

 

ballardw
Super User

@primmer300174 wrote:

I have to convert each duration into 30 minute intervals for comparing against the scheduled activity which is in 30 minute intervals. 

This is what the Resource planning area have given me and will not change this. I am trying to work out how many agents I would have (whether fully or partly) in that 30 minute interval. I have examples where a break has been place at 10:55:00 - 11:05:00 which would mean I need to have the MyStart as 10:55:00 - MyEnd 11:05:00 and then an additional row that would say MyStart as 11:05:00 and MyEnd as 11:30:00.

Hope this make sense and clarifies the confusion.

 


As an aside, you keep saying "30 minute interval" and then show something like "MyStart as 10:55:00 - MyEnd 11:05:00 and then an additional row that would say MyStart as 11:05:00 and MyEnd as 11:30:00." Neither of these start/end pairs have a 30 minute interval. 

This sounds more like you have to add an observation to the data set when an existing interval that does not end in either 00 or 30 minutes such that the additional observation starts at the end of the existing observation ends at such a multiple. Is this a clearer understanding of what your requirement is? If so, is there ever a requirement to add more than one observation and what in the data tells you that a particular observation should have such multiple extensions.

 

If the objective is to count intervals then I think that you don't need to add anything to the data. The INTCK function allows for custom intervals involving multiples of an existing unit.

Consider this program which has a given start period and then increments and end period value starting one minute later and running for a bit.

 

data example;
   starttime = '01:23:00't;
   do endtime   = '01:24:00't to '02:12:00't by 60;
      intervals = intck('minute30',starttime,endtime);
      output;
   end;
   format starttime endtime time.;
run;

If you examine the output you will see that the interval count returned is 0 until the endtime value reaches 1:30:00 and then increments, then again at 2:00:00.

So depending on your need you may either use this interval directly or add 1 to get a 3 for the number of 30 minute periods involved.

 

 

 

 

BTW, computers are stupid and "30 minute interval" with no other information could start at 5 and go to 35 minutes or any other start/end. You need to explicitly state the periods need to end at minute 00 and 30.

 

Tom
Super User Tom
Super User

Using the MINUTE30 interval should work.

data want;
  set have;
  do interval=0 to intck('minute30',start,stop);
    MyStart=max(start,intnx('minute30',start,interval,'b'));
    MyEnd=min(stop,intnx('minute30',start,interval+1,'b'));
    output;
  end;
  format mystart myend tod8.;
run;

Result

Screenshot 2025-06-15 at 4.56.54 PM.png

hackathon24-white-horiz.png

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

SAS Enterprise Guide vs. SAS Studio

What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.

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
  • 16 replies
  • 3791 views
  • 7 likes
  • 8 in conversation