Search code examples
datetimesasdatetime-formatinformat

Specifying picture informant in order to read specific datetme string


I would like to read the "19-APR-21 18.17.06.301100" the string into a DATETIME and display accordingly. In order to achieve that I'm intending to define a display format and an informat as provided in the example below.

Example

* Define formats to read and display data;
* Input format;
PROC FORMAT LIB=work;
    PICTURE indte other = '%d-%B-%y %H.%M.%S.%s'
        (DATATYPE=DATETIME);
RUN;

* Nice display format;
PROC FORMAT LIB=work;
    PICTURE outdte other = '%d %B %y %H:%M'
        (DATATYPE=DATETIME);
RUN;

* Test with sample data;
DATA text;
    strdate = "19-APR-21 18.17.06.301100";
RUN;
    
* Apply informat and display format;
DATA pretty(RENAME=(strdate=nicedte));
    SET work.text;
    ATTRIB strdate INFORMAT=indte.;
    FORMAT strdate outdte.;
RUN;
    

Problems/questions

  1. The DATA pretty procedure is not able to load the define formats and returns the following error:

    NOTE 485-185: Informat $INDTE was not found or could not be loaded.

    NOTE 484-185: Format $OUTDTE was not found or could not be loaded.

  2. Is this an efficient way of doing this for the data that in the proper process is sourced via: infile <file ref created by filename> delimiter=',' stopover firstobs=2 dsd lrecl=32767;?

Solution

  • PICTURE is used to create a FORMAT, not an INFORMAT.

    The ANYDTDTM informat should handle strings in that style. But it will ignore the fractions of a second.

    DATA text;
      strdate = "19-APR-21 18.17.06.301100";
      datetime = input(strdate,anydtdtm.);
      format datetime datetime26.6 ;
      put (_all_) (=/);
    RUN;
    

    Results:

    strdate=19-APR-21 18.17.06.301100
    datetime=19APR2021:18:17:06.000000
    

    If you need the fractions of a second then parse the string and read it separately.

      datetime  = dhms(input(strdate,date9.)
                      ,input(scan(strdate,2,' .'),2.)
                      ,input(scan(strdate,3,' .'),2.)
                      ,input(scan(strdate,4,' .'),2.)
                      +input(scan(strdate,5,' .'),6.6)
                  );