La función intnx()
es una de las funciones más útiles, junto con intck(), para el trabajo con fechas y merece por si misma una entrada en el blog. Vamos a empezar viendo su sintaxis básica y su uso:
Sintáxis
intnx(intervalo, fecha, incremento)
Esta función calcula de una forma fácil la fecha que se deriva de sumar cierta cantidad (incremento) de periodos de tiempo (intervalo) a una fecha concreta. Por ejemplo, intnx('month','1jan2020'd,5)
da como resultado el 1 de junio de 2020, porque si a partir del 1 de enero sumamos 5 meses es el 1 de junio. Esto es tremendamente útil porque sumar meses considerándolos como 30 días no da una fecha concreta del mes que buscamos si no que varía en función de la cantidad de días que tengan los meses intermedios.
Con respecto a los intervalos que podemos usar están, entre otros: ‘day’, ‘week’, ‘month’, ‘qtr’ (trimestre), ‘year’. La fecha debe incluirse en formato numérico (no vale una cadena de texto) y el incremento es cualquier número entero positivo o negativo.
intnx(‘month’,’1jul2021’d,-7) |
‘1jan2021’d |
intnx(‘day’,’15jul2021’d,-15) |
‘1jul2021’d |
intnx(‘week’,’11oct2021’d,-1) |
‘4oct2021’d |
intnx(‘year’,’1jan2021’d,-1) |
‘1jan2020’d |
intnx(‘qtr’,’1jan2021’d,-1) |
‘1oct2020’d |
El alineamiento
Adicionalmente disponemos de un cuarto parámetro; el alineamiento, que indica en qué parte del intervalo temporal que hemos definido queremos situarnos: al principio, a la mitad, al final o el mismo día que la fecha indicada. El alineamiento tomará respectivamente los valores: ‘B’, ‘M’, ‘E’, ‘S’, por sus siglas en inglés. El valor ‘B’ es el valor por defecto si no se indica nada.
intnx(‘year’,’6jul2021’d,0) |
‘1jan2021’d |
Como ‘B’ es el valor por defecto, si no indicamos nada obtendremos el primer día del mismo (0) periodo (year) de la fecha indicada (‘6jul2021’). |
intnx(‘year’,’6jul2021’d,0,’E’) |
’31dec2021’d |
Cuando se indica ‘E’ obtendremos el último día del mismo (0) periodo (year) a la fecha indicada (‘6jul2021’). |
intnx(‘year’,’6jul2021’d,1,’S’) |
‘6jul2022’d |
Con ‘S’ obtendremos la misma fecha del siguiente periodo. |
intnx(‘week’,’6jul2021’d,1,’S’) |
’13jul2021’d |
En este caso, como se indican sumar un periodo de una semana y tenemos el alineamiento nos indica que debe ser el mismo día de la semana (martes), obtendremos la fecha de 7 días después. |
intnx(‘week’,’6jul2021’d,1,’E’) |
’17jul2021’d |
Utilizar el alineamiento ‘E’ indica tener que ir al último día de la siguiente semana, el sábado. Las semanas comienzan el domingo. |
Con todo esto, ¿cómo obtener los registros correspondientes al mes anterior de una tabla cuyos registros están informados con un campo fecha?
intnx('month',date(),-1,'B') <= fecha <= intnx('month',date(),-1,'E')
Esta condición permite obtener todos los registros del mes anterior al actual de una tabla. Lo mismo sería para obtener la semana anterior o el trimestre anterior.
Multiplicadores de intervalo
Finalmente, existe la posibilidad de añadir multiplicadores a los intervalos. Para ello, se añade simplemente un número detrás del nombre del intervalo. Por ejemplo: intnx('month3',date(),1)
sería una forma de indicar la fecha correspondiente al inicio del próximo trimestre y es equivalente a expresarlo como intnx('qtr',date(),1)
.
intnx(‘month3’,’1jan2021’d,1) |
‘1apr2021’d |
Obtenemos el primer día del trimestre siguiente al actual. |
intnx(‘month2’,’1jan2021’d,1) |
‘1mar2021’d |
Utilizando el multiplicador 2 con el mes obtendremos periodos de 2 meses. |
intnx(‘month2.2′,’1mar2021’d,0,’B’) |
‘1feb2021’d |
Aquí utilizamos el multiplicador para definir periodos temporales de dos meses, pero lo hemos modificado con un índice «.2» que indica que estos periodos temporales de dos meses comienzan el segundo mes del año. Por tento la fecha de inicio de ese periodo es el 1 de febrero. |
intnx(‘month2.2′,’1mar2021’d,0,’E’) |
’31mar2021’d |
Al igual que en el ejemplo anterior, utilizamos el mismo multiplicador y pedimos la última fecha de ese periodo que es el 31 de marzo. ‘month2.1’ sería equivalente a ‘month2’. |
Intervalos personalizados
Vistas todas las opciones que nos ofrece predefinidas intnx()
aún podemos definir intervalos propios en vez de los conocidos ‘month’ o ‘year’. Pongámonos en el caso de una empresa que realice los cierres mensuales el día 16 de cada mes. Una opción sería utilizar el intervalo predefinido ‘semimonth2.2’.
intnx(‘semimonth2.2′,’1jan2021’d,0,’B’) |
’16dec2020’d |
intnx(‘semimonth2.2′,’1jan2021’d,0,’E’) |
’15jan2021’d |
Sin embargo, esta empresa tiene una particularidad, y es que los meses de febrero cierran el día 14, no el 15. Para resolver esto tenemos dos opciones o añadir una lógica condicionada al mes en curso o definir nuestro propio intervalo. Para definir nuestro propio intervalo utilizaremos la instrucción options intervalds
a la que se le pasan el nombre del intervalo y el de la tabla que contiene la definición de esos intervalos. Luego definimos esa tabla de la manera en que se muestra y ya podremos utilizar nuestros propios intervalos con la función intnx()
y de la misma manera que los predefinidos:
options intervalds=(cierre=dstest);
data dstest;
format begin end date9.;
begin='16jan2021'd; end='14feb2021'd; output;
begin='15feb2021'd; end='15mar2021'd; output;
begin='16mar2021'd; end='15apr2021'd; output;
begin='16apr2021'd; end='15jun2021'd; output;
begin='16jun2021'd; end='15jul2021'd; output;
begin='16jul2021'd; end='15aug2021'd; output;
begin='16aug2021'd; end='15sep2021'd; output;
begin='16sep2021'd; end='15oct2021'd; output;
begin='16oct2021'd; end='15nov2021'd; output;
begin='16nov2021'd; end='15dec2021'd; output;
begin='16dec2021'd; end='15jan2022'd; output;
begin='16jan2022'd; end='14feb2022'd; output;
begin='15feb2022'd; end='15mar2022'd; output;
begin='16mar2022'd; end='15apr2022'd; output;
begin='16apr2022'd; end='15jun2022'd; output;
begin='16jun2022'd; end='15jul2022'd; output;
begin='16jul2022'd; end='15aug2022'd; output;
begin='16aug2022'd; end='15sep2022'd; output;
begin='16sep2022'd; end='15oct2022'd; output;
begin='16oct2022'd; end='15nov2022'd; output;
begin='16nov2022'd; end='15dec2022'd; output;
begin='16dec2022'd; end='15jan2023'd; output;
run;
data salida;
format fecha_inicio fecha_fin date9.;
fecha_inicio=intnx('cierre',date(),0,'B');
fecha_fin=intnx('cierre',date(),0,'E');
run;