Crear una cadena YYYYMMDD en un simple .BAT
A veces uno necesita hacer cosas que parecen simples y acaban siendo trabajosas. En mi oficina utilizo una máquina que tiene instalado el Microsoft ISA Server 2004 y, por razones que no vienen al caso, necesitaba todos los días transferir el fichero de registro diario a otro servidor. No habría problema...si no fuera porque dicho fichero tiene un nombre que cambia cada día. En concreto tiene la fecha del día en que se crea en formato YYYYMMDD. ¿Cómo crear esta cadena sin necesidad de programar algo en Perl, C#, etc. (lo cual sería exagerar un poco)?
Pues resulta que los scripts de Windows pueden hacer esta operación. Como sabemos, la variable %DATE% tiene la fecha del día actual, en un formato que depende del sistema operativo y de la configuración regional. Por ejemplo en Windows 2000 configurado en Español la fecha de hoy sería lun, 30/10/2006, o en Windows XP configurado en Inglés de Estados Unidos la fecha de hoy sería 10/30/2006.
Bueno, pues podemos hacer operaciones de extracción de subcadenas con esa variable. El tema de que aparezca o no el día de la semana no nos afecta si las subcadenas de año, mes y día las extraemos contando desde el final. Lo que sí nos afecta es la configuración regional, por lo que antes de realizar estas operaciones en un script hay que asegurarse de cómo está configurado el formato de fecha. El ejemplo está hecho para formato europeo (DD/MM/YYYY):
set year=%DATE:~-4,4%
set month=%DATE:~-7,2%
set day=%DATE:~10,2%
set today=%year%%month%%day%
Fácil, ¿eh?
...Pero para el uso que yo quería darle, esto es sólo la mitad del problema.
Realmente lo que yo necesitaba no era la fecha de hoy sino la de ayer. ¿Cómo se calcula la fecha de ayer?
- Si no estamos a día 1, sólo hay que restar 1 al día.
- Si estamos a día 1, hay que pasar al mes anterior y el número de día ha de ser 28, 29, 30 o 31 dependiendo del mes y del año. En concreto, si el mes anterior era Abril, Junio, Septiembre o Noviembre, el último día del mes es el 30. Si era febrero, es 28 excepto si el año es bisiesto (años divisibles por 4 y no divisibles por 100 o años divisibles por 400).
- Si estamos a 1 de enero hay que restar 1 al año.
set year=%DATE:~-4,4%
set month=%DATE:~-7,2%
set day=%DATE:~10,2%
REM Restamos 0 al mes para convertirlo en un número sin ceros
REM a la izquierda (si es necesario los volveremos a poner)
set /a month=%month%-0
REM Restamos 1 al día
set /a day=%day%-1
if %day% neq 0 goto end
REM Si llegamos aquí es porque hay que pasar al mes anterior.
set day=31
set /a month=%month%-1
if %month% neq 2 goto nofeb
REM Si llegamos aquí es que el mes anterior es Febrero
set /a leap=%year%%4
if %leap% neq 0 goto noleap
REM Si llegamos aquí, el año es divisible por 4 y por tanto
REM potencialmente bisiesto
set /a leap=%year%%100
if %leap% neq 0 goto leap
REM Si llegamos aquí, el año es divisible por 4 y por 100 y
REM hay que comprobar si es divisible por 400
set /a leap=%year%%400
if %leap% neq 0 goto noleap
:leap
REM Es bisiesto
set day=29
goto nofeb
:noleap
REM No es bisiesto
set day=28
:nofeb
if %month% equ 4 set day=30
if %month% equ 6 set day=30
if %month% equ 9 set day=30
if %month% equ 11 set day=30
REM Ahora, el día tendrá el valor 28, 29, 30 y 31.
REM Queda comprobar si hemos pasado de año.
if %month% neq 0 goto end
REM Si llegamos aquí hay que cambiar de año
set month=12
set /a year=%year%-1
:end
REM Finalmente hay que poner ceros a la izquierda del día y
REM mes en el caso de que sean menores que 10.
if %day% lss 10 set day=0%day%
if %month% lss 10 set month=0%month%
set yesterday=%year%%month%%day%
Como se ve, es sencillo, pero pesado de tener que hacer cada vez, así que vale la pena tener siempre guardada una versión para poderlo llamar desde cualquier otro script, ya que bien pensado esta es una tarea que tiene pinta de aparecer en muchos contextos diferentes.