Al desarrollar scripts, a veces es necesario trabajar con fechas utilizando la herramienta GNU date, parte del paquete coreutils. En este artículo voy a explicar cómo restar fechas en Bash, a fin de obtener la cantidad de semanas, días, horas o segundos entre las mismas.
Supongamos que deseamos contar la cantidad de días entre dos fechas, tarea no trivial en absoluto. Por ejemplo, necesitamos contar la cantidad de días desde el 11 de diciembre de 2015 hasta la actualidad.
Utilizando Bash, es posible recurrir al constructor doble paréntesis (( ... ))
el cual permite expandir y evaluar expresiones aritméticas.
Para comenzar, vamos a establecer el rango de fechas utilizando dos variables desde (FECHA_INICIO
) y hasta (FECHA_FIN
):
$ FECHA_INICIO=$(date --date=151211 +%s) $ FECHA_FIN=$(date +%s)
El formato de ambas fechas consiste en la cantidad de segundos transcurridos desde el primero de enero de 1970 (%s
). De esta forma es posible luego restar ambas cantidades de segundos para luego convertir a la unidad deseada.
$ SEGUNDOS=$(( $FECHA_FIN - $FECHA_INICIO )) $ HORAS=$(( $SEGUNDOS / 3600 )) $ DIAS=$(( $HORAS / 24 )) $ SEMANAS=$(( $DIAS / 7 ))
Al día de la fecha (8 de agosto de 2017) el resultado es el siguiente:
root@linuxito:~# date Tue Aug 8 07:41:25 EDT 2017 root@linuxito:~# FECHA_FIN=$(date +%s) root@linuxito:~# FECHA_INICIO=$(date --date=151211 +%s) root@linuxito:~# SEGUNDOS=$(( $FECHA_FIN - $FECHA_INICIO )) root@linuxito:~# HORAS=$(( $SEGUNDOS / 3600 )) root@linuxito:~# DIAS=$(( $HORAS / 24 )) root@linuxito:~# SEMANAS=$(( $DIAS / 7 )) root@linuxito:~# echo $SEMANAS 86 root@linuxito:~# echo DIAS = $DIAS DIAS = 606 root@linuxito:~# echo HORAS = $HORAS HORAS = 14550
Por supuesto es posible utilizar paréntesis y operadores aritméticos y lógicos dentro de la expresión. Por ejemplo, si sólo nos interesa la cantidad de días, es posible resolverlo en una única línea:
root@linuxito:~# FECHA_FIN=$(date +%s) root@linuxito:~# FECHA_INICIO=$(date --date=151211 +%s) root@linuxito:~# DIAS=$(( ($FECHA_FIN - $FECHA_INICIO) / (60*60*24) )) root@linuxito:~# echo $DIAS 606
Además es posible abrir una subshell dentro de la expresión:
root@linuxito:~# DIAS=$(( ($(date +%s) - $(date --date=151211 +%s) / (60*60*24) )) root@linuxito:~# echo $DIAS 606
Referencias
- Advanced Bash-Scripting Guide: The Double-Parentheses Construct
man bash
man date