Thank you for the help and your time.
I have the following time format in is8601 format(PT14M), which I want to convert into MM: SS (14:00) character format. if its PT2M then it should display as "02:00"
data x;
is8601 = 'PT14M';
output;
is8601 = 'PT2M';
output
/* mmss_char = "14:00";*/
run;
For example you might use SCAN() to parse the string into the parts that should have digit strings and convert them into numbers you can convert into an actual TIME value. Then you can convert that into you MMSS string.
data have;
input duration $20.;
if duration=:'PT' then do;
time=input('0'||scan(duration,-3,'PTMS'),32.)*60
+input('0'||scan(duration,-2,'PTMS'),32.)
;
if char(duration,length(duration))='M' then time=time*60;
mmss=substr(put(time,B8601TM6.),3);
end;
format time time12.;
cards;
PT14M
PT2M
PT1M25S
PT65S
;
So you want to assume that the unknown number of seconds is zero?
Similarly for hours?
Playing around it looks like the $N8601B informat can convert those variable strings into fixed position strings.
data have;
input duration $20.;
normal = input(duration,$N8601B50.);
cards;
PT14M
PT2M
P0DT14M
2023-01-02T01:02:03
2023-11-22T01:02:03
;
Result:
Obs duration normal 1 PT14M FFFFFFFFF14FFFFC 2 PT2M FFFFFFFFF02FFFFC 3 P0DT14M FFFFF00FF14FFFFC 4 2023-01-02T01:02:03 2023102010203FFD 5 2023-11-22T01:02:03 2023B22010203FFD
So the Minutes are in positions 10 and 11 and seconds in 12 and 13. The unknown fields are coded as FF.
data have;
input duration $20.;
normal = input(duration,$N8601B16.);
mmss = substr(normal,10,4);
mmss = tranwrd(mmss,'FF','00');
cards;
PT14M
PT2M
P0DT14M
2023-01-02T01:02:03
2023-11-22T01:02:03
;
Thank you for the suggestions. Just an update on your questions: Our variables only have the minutes and seconds. This is the playtime of a video. And all the videos are less than an hour, so, it never gets into hours; if no one watches the video then duration is missing by default in the variable.
I played a bit with the following code. Please suggest to me if it has any pitfalls in it.
data have;
input duration $20.;
cards;
PT14M
PT2M
;
run;
data want;
set have;
if duration ne '' then duration = strip(put((input(substr(duration, 3, length(duration)-3), best.)*60),mmss5.));
duration = ifc(length(duration) =5, duration,"0"||strip(duration));
if duration = '0' then duration ='';
run;
If you are only using a subset of ISO8601 then you should be able to use simpler methods to parse the strings.
You should increase your examples to cover all of the possible types of values to make sure your algorithm can handle the values you get. For example do you ever have minutes and seconds? Seconds only? Do you always have PT as the first two characters?
For example you might use SCAN() to parse the string into the parts that should have digit strings and convert them into numbers you can convert into an actual TIME value. Then you can convert that into you MMSS string.
data have;
input duration $20.;
if duration=:'PT' then do;
time=input('0'||scan(duration,-3,'PTMS'),32.)*60
+input('0'||scan(duration,-2,'PTMS'),32.)
;
if char(duration,length(duration))='M' then time=time*60;
mmss=substr(put(time,B8601TM6.),3);
end;
format time time12.;
cards;
PT14M
PT2M
PT1M25S
PT65S
;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.