SAS: Convertir de texto a fecha

Convertir de un texto a una fecha es una pregunta habitual para nuevos programadores en SAS, hay varios enfoques válidos para hacerlo:
La mejor solución al problema es aplicar la función input() sobre la cadena de entrada para cambiarle el informat al nuevo campo (fecha) e inmediatamente después aplicar el formato con put(). Incluyo dos ejemplos distintos de formato de entrada y de salida:

data SALIDA2;
    cadena1 = "2021/07/15";
    fecha2 = put(input(cadena,yymmdd10.),date9.);
    cadena2 = "20220115";
    fecha2 = input(put(cadena,z8.),yymmdd8.);
run;

Otra solución es tratar la cadena de texto obteniendo cada uno de los tres componentes de la fecha: día, mes, año y pasándolos como parámetro a una función mdy() para formar la fecha.

data SALIDA;
    cadena = "2021/07/15";
    dia = input(put(substr(cadena,9,2),$2.),8.);
    mes = input(put(substr(cadena,6,2),$2.),8.);
    anyo = input(put(substr(cadena,1,4),$4.),8.);
    fecha = put(mdy(mes,dia,anyo),date9.);
run;

Este enfoque es engorroso y largo pero da total libertad al programador: Por ejemplo, en caso de que la entrada no sea exactamente una fecha, sino un dato como «202107» pero sin embargo quisiéramos conseguir una salida que fuera el primer día del mes.

data SALIDA;
    cadena = "202107";
    mes = input(put(substr(cadena,5,2),$2.),8.);
    anyo = input(put(substr(cadena,1,4),$4.),8.);
    fecha = put(mdy(mes,1,anyo),date9.);
run;

Macro SAS: Validar teléfonos (España)

Esta macro que incluyo a continuación permite validar número de teléfonos de España, aunque no se encuentre normalizados, esto es, contengan el prefijo internacional o no, o estén separados por algún tipo de separador o de espacio. Al final se ofrecen los números de teléfonos normalizados y sin prefijo.

Esta macro solo hace una verificación del formato del número del teléfono, pero no sabe distinguir entre números reales o no. Para hacer este tipo de verificaciones tenemos servicios que dan información vía API (protocolo de comunicación entre sistemas) devolviendo un fichero JSON sobre el tipo de teléfono, operador, país, etc. Espero poder poner un ejemplo sobre cómo integrar un servicio de terceros como este en un futuro (Hazme un comentario si estás interesado en ello).

%macro telefono(tabla=,campo=);
data &tabla;
set &tabla;
&campo = compress(&campo,' ','P');
if substr(&campo,1,4) = '0034' then &campo = substr(&campo,5);
if substr(&campo,1,2) = '34' then &campo = substr(&campo,3);
if substr(&campo,1,1) not in ('6','7','8','9') or
substr(&campo,1,2) in ('80','90') or
length(&campo) ne 9 then ind_valido = 0;
else ind_valido = 1;
run;
%mend;

Puedes probar con estos ejemplos la macro:

data clientes;
    format telefono $20.;
    input telefono;
    datalines;
    9851246323
    981122044
    +34666777888
    902123123
    0034-616875794
    +0034 615 789 456
    658.452.187
    001 32157979
    34715845978
    888123456
    (95)6543232
    ;
run;*/

%telefono(tabla=clientes,campo=telefono);

Truco SAS: Convertir fechas datetime de Unix a SAS

Como sabemos, los formatos de fechas en SAS y en otros sistemas operativos o bases de datos se interpretan y se almacenan como números que representan el número de días (o de segundos, en el caso de los datetime) transcurridos desde una fecha de origen. Las fechas anteriores a ella se almacenan como números negativos.

Lo que puede cambiar entre estos distintos sistemas es esa fecha origen a partir de la que se empieza a contar, de forma que una misma cifra puede representar fechas distintas dependiendo de qué sistema haya generado esa fecha. Esto da lugar a algunos problemas que debemos resolver cuando se realizan migraciones de datos de un sistema a otro. En nuestro caso, como programadores en SAS, debemos tener cuidado al importar fechas generadas con el timestamp de Unix y tener en cuenta que Unix no comienza a contar las fechas desde la misma fecha origen que SAS. Mientras SAS comienza a contar en ’01jan1960′; Unix comienza a contar en ’01jan1970′. Esos 10 años de diferencias hay que tenerlos en cuenta.

Por ello, si tenemos un datetime generado en Unix será necesario aplicar la siguiente corrección para que al convertir el número en fecha SAS éstas sean equivalentes:

fecha_SAS = fecha_Unix + 315619200;

Esa cantidad que sumamos es el número de segundos que representan esos 10 años. Existe otra forma de hacerlo, quizás un poco más elegante, que es utilizando la función dhms():

fecha_SAS = dhms('01jan1970'd, 0, 0, fecha_Unix);

La función dhms() construye un datetime a partir de una fecha y un número de horas, minutos y segundos. Con la instrucción anterior, se generará un datetime sumando el número de segundos expresados en la fecha_Unix a la fecha origen de Unix, que es el ’01jan1970′. Es una forma más elegante y además resulta más fácil recordar la fecha de origen de Unix, que el número tan grande de segundos que representan esa diferencia.
Si las fechas de Unix están representadas en milisegundos solo debemos utilizar una pequeña variante sobre lo anterior:

fecha_SAS = dhms('01jan1970'd, 0, 0, fecha_Unix/1000);