DATA Step, Macro, Functions and more

Convert dates in a text field

Accepted Solution Solved
Reply
Contributor
Posts: 54
Accepted Solution

Convert dates in a text field

I am starting with a variable that has fully formed SQL logic in it.

For example, Select * From Trans where Trans_date >= '2011-01-01'

The Trans table is now a local SAS data set, so to run the SQL stored in the variable, I need to change the date format from 'YYYY-MM-DD' to 'd-mmm-yy'd

I can do this if I create a lookup table for each date value and use tranwrd to replace them all but it seems to me there would be a more elegant way of doing this.

Since the dates are stored in the text field with the rest of the logic, perhaps trnwrd is the best way to go. Can I get your thoughts/solutions on how best to accomplish this?

Thanks!


Accepted Solutions
Solution
‎12-16-2011 12:12 PM
Valued Guide
Posts: 2,177

Convert dates in a text field

while Art was working on his, I was working on this (someday I'll get into these prx.... but for now,

data have;

   input;

   line =_infile_;

   list; cards4;

Select * From Trans where

Field1 <> 'D1' AND

Field2 <> 13 AND Field2 <> 61 AND Field2 <> 86 AND

Field3 <> '02' AND Field3 <> '16' AND Field3 <> '86' AND

Tran_dt > '2011-03-26' AND Tran_dt < '2011-04-23'

;

Select * From Trans where

Field1 <> 'D1' AND

Tran_dt > '2011-11-01'

;

;;;;

data want;

   set have;

   date_pos = find( line, 'tran_dt', 'i' );

   do while(date_pos);

      old1 = scan( substr( line, date_pos), 2, "'" );

      open_pos = find( line, "'",date_pos);

      clos_pos = find( line, "'",open_pos +2 );

      substr( line, open_pos+1,11) = put( input( old1, yymmdd10.), date9.) !! "'d";

      date_pos = find( line, 'tran_dt', 'i', clos_pos );

   end;

run;

this works by replacing the 'yyyy-mm-dd' with 'ddMMMyyyy'd

View solution in original post


All Replies
PROC Star
Posts: 7,471

Convert dates in a text field

If all of your statements are like the one shown in your example, you might be able to use something like:

data have;

  informat current $60.;

  input current &;

  cards;

Select * From Trans where Trans_date >= '2011-01-01'

Select * From Trans where Trans_date >= '2011-02-02'

;

data want (drop=x);

  set have;

  x=index(current,"'");

  need=catt(substr(current,1,x-1),"'",

   put(input(compress(substr(current,x),"'"),

    anydtdte12.),date9.),

   "'d");

run;

Contributor
Posts: 54

Convert dates in a text field

I like that! I do have some competing fields for that index though.

Here is a more real world example. I should have known enough to include it the first time, sorry:

Select * From Trans where

Field1 <> 'D1' AND

Field2 <> 13 AND Field2 <> 61 AND Field2 <> 86 AND

Field3 <> '02' AND Field3 <> '16' AND Field3 <> '86' AND

Tran_dt > '2011-03-26' AND Tran_dt < '2011-04-23'

PROC Star
Posts: 7,471

Re: Convert dates in a text field

I am only learning regular expressions, thus I'm sure that a more elegant way of writing the following exists.  However, it does work for your examples:

/*The following file contains all of your examples*/

data have;

  informat current $250.;

  infile "c:\trans.txt" lrecl=260;

  input current &;

run;

options datestyle=ymd;

data want (drop=x _Smiley Happy;

  set have;

  _dt_pattern_num=prxparse(

   "/\d\d\d\d\-\d\d\-\d\d/o");

  x=1;

  do while (x gt 0);

    x = prxmatch(_dt_pattern_num,current);

    /* If found, then parse date */

    if x then do;

      current=catt(substr(current,1,x-1),

        put(input(substr(current,x,10),

        anydtdte12.),date9.),"'d",

        substr(current,x+11));

    end;

  end;

run;

Contributor
Posts: 54

Convert dates in a text field

For only just learning regular expressions, you sure do a good job of making stuff that works. Thanks!

Trusted Advisor
Posts: 1,301

Convert dates in a text field

The regular expression can be rewritten as /\d{4}-\d{2}-\d{2}/

Also you can use prxsubstr instead of prxmatch to help with the collection of the data.

Solution
‎12-16-2011 12:12 PM
Valued Guide
Posts: 2,177

Convert dates in a text field

while Art was working on his, I was working on this (someday I'll get into these prx.... but for now,

data have;

   input;

   line =_infile_;

   list; cards4;

Select * From Trans where

Field1 <> 'D1' AND

Field2 <> 13 AND Field2 <> 61 AND Field2 <> 86 AND

Field3 <> '02' AND Field3 <> '16' AND Field3 <> '86' AND

Tran_dt > '2011-03-26' AND Tran_dt < '2011-04-23'

;

Select * From Trans where

Field1 <> 'D1' AND

Tran_dt > '2011-11-01'

;

;;;;

data want;

   set have;

   date_pos = find( line, 'tran_dt', 'i' );

   do while(date_pos);

      old1 = scan( substr( line, date_pos), 2, "'" );

      open_pos = find( line, "'",date_pos);

      clos_pos = find( line, "'",open_pos +2 );

      substr( line, open_pos+1,11) = put( input( old1, yymmdd10.), date9.) !! "'d";

      date_pos = find( line, 'tran_dt', 'i', clos_pos );

   end;

run;

this works by replacing the 'yyyy-mm-dd' with 'ddMMMyyyy'd

Contributor
Posts: 54

Convert dates in a text field

Works right out of the box. Thanks!

PROC Star
Posts: 7,471

Convert dates in a text field

Both Peter's and my solutions should work right out of the box (at least for dates that appear as yyyy-mm-dd, but, realize that the regular expression method would be better if there is more than one date variable.  Peter's code would have to be expanded if you had, say, tran_dt and recv_dt or the like.

Contributor
Posts: 54

Convert dates in a text field

You're right. Having the ability to add new dates without re-coding is the way to go.

When using your solution, it retains the trailing single quote. All the dates are correctly replaced but look like this '25NOV2011'd'

Is there a way to alter your code to remove the single quote after the d?

PROC Star
Posts: 7,471

Re: Convert dates in a text field

Yes, there was an error in my original code.  I just changed it and the extra quote is now removed.

Contributor
Posts: 54

Convert dates in a text field

Ah ha! I got it.

I had to increase the substring constant.

substr(FDWCQueues,x+ 11

Super User
Posts: 10,028

Re: Convert dates in a text field

data have;
   input;
   line =_infile_;
   list; cards4;
Select * From Trans where
Field1 <> 'D1' AND
Field2 <> 13 AND Field2 <> 61 AND Field2 <> 86 AND
Field3 <> '02' AND Field3 <> '16' AND Field3 <> '86' AND
Tran_dt > '2011-03-26' AND Tran_dt < '2011-04-23'
;
Select * From Trans where
Field1 <> 'D1' AND
Tran_dt > '2011-11-01'
;
;;;;
run;
data want(keep=line);
 set have;
 pid=prxparse("/'\s*\d{4}\s*-\s*\d{1,2}\s*-\s*\d{1,2}\s*'/o");
 start=1;stop=length(line);
 call prxnext(pid,start,stop,line,position,length);
 do while(position > 0);
 date=put(input(dequote(substr(line,position,length)),yymmdd20.),date9.);
 line=substr(line,1,position-1)||quote(date)||'d'||substr(line,position+length);
 call prxnext(pid,start,stop,line,position,length);
 end;
run;




Ksharp

Valued Guide
Posts: 2,177

Convert dates in a text field

Ksharp

very good, supporting any single quoted date of form yyyy-mm-dd or yyyy-m-d and with or without a variable name nearby

Super User
Posts: 10,028

Convert dates in a text field

You are welcome.  Peter.

Merry Christmas!

Ksharp

🔒 This topic is solved and locked.

Need further help from the community? Please ask a new question.

Discussion stats
  • 18 replies
  • 391 views
  • 6 likes
  • 6 in conversation