linux - programas - scripts bash ejemplos
Obtenga la fecha de ayer en bash en Linux, DST-safe (7)
Tengo un script de shell que se ejecuta en Linux y usa esta llamada para obtener la fecha de ayer en YYYY-MM-DD
:
date -d "1 day ago" ''+%Y-%m-%d''
Funciona la mayor parte del tiempo, pero cuando el script se ejecutó ayer a la mañana del 2013-03-11 0:35 CDT
, devolvió "2013-03-09"
lugar de "2013-03-10"
.
Presumiblemente, el horario de verano (que comenzó ayer) es el culpable. Supongo que de la forma en que se implementó "1 day ago"
se restaron 24 horas, y 24 horas antes de 2013-03-11 0:35 CDT
fue 2013-03-09 23:35 CST
, lo que condujo al resultado de "2013-03-09"
.
Entonces, ¿cuál es una buena manera de proteger el DST de la fecha de ayer en bash en Linux?
Aquí una solución que también funcionará con Solaris y AIX.
La manipulación de la zona horaria es posible para cambiar el reloj algunas horas. Debido al horario de verano, las 24 horas pueden ser hoy o anteayer.
Estás seguro de que ayer fue hace 20 o 30 horas. ¿Cúal? Bueno, el más reciente que no es hoy.
echo -e "$(TZ=GMT+30 date +%Y-%m-%d)/n$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1
El parámetro -e utilizado en el comando echo es necesario con bash, pero no funcionará con ksh. En ksh puede usar el mismo comando sin el distintivo -e.
Cuando su script se utilizará en diferentes entornos, puede iniciar el script con #! / Bin / ksh o #! / Bin / bash. También podría reemplazar el / n por una nueva línea:
echo "$(TZ=GMT+30 date +%Y-%m-%d)
$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1
Bash bajo Mac OSX es ligeramente diferente.
Para ayer
echo `date -v-1d +%F`
Para la semana pasada
echo `date -v-1w +%F`
Creo que esto debería funcionar, independientemente de con qué frecuencia y cuándo lo ejecutes ...
date -d "yesterday 13:00" ''+%Y-%m-%d''
Esto también debería funcionar, pero quizás sea demasiado:
date -d @$(( $(date +"%s") - 86400)) +"%Y-%m-%d"
Si está seguro de que el script se ejecuta en las primeras horas del día, simplemente puede hacer
date -d "12 hours ago" ''+%Y-%m-%d''
Por cierto, si la secuencia de comandos se ejecuta todos los días a las 00:35 (a través de crontab?) Debe preguntarse qué sucederá si un cambio de horario de verano cae en esa hora; la secuencia de comandos no se pudo ejecutar o ejecutar dos veces en algunos casos. Sin embargo, las implementaciones modernas de cron
son bastante ingeniosas en este sentido.
puedes usar
date -d "30 days ago" +"%d/%m/%Y"
para obtener la fecha de hace 30 días, de manera similar puede reemplazar 30 por x cantidad de días
Solo usa la date
y los segundos de confianza:
Como bien lo señala, muchos de los detalles sobre el cálculo subyacente están ocultos si se basa en la aritmética del tiempo en inglés. Los -d 1 day ago
-d yesterday
y -d 1 day ago
tendrán un comportamiento diferente.
En cambio, puede confiar de manera confiable en los segundos (documentados con precisión) desde la época unix UTC y la aritmética bash para obtener el momento que desee:
date -d @$(( $(date +"%s") - 24*3600)) +"%Y-%m-%d"
Esto fue señalado en otra answer . Este formulario es más portátil en plataformas con diferentes indicadores de línea de comando de date
, es independiente del lenguaje (por ejemplo, "ayer" vs "hier" en la configuración regional francesa), y francamente (a largo plazo) será más fácil de recordar, porque bueno, Ya lo sabes. De lo contrario, podría seguir preguntándose: "¿Fue hace -d 2 hours ago
o -d 2 hour ago
?" o "¿Es -d yesterday
o -d 1 day ago
que quiero?"). El único truco aquí es el @
.
Armado con bash y nada más:
Bash únicamente en bash, también puedes obtener la hora de ayer, a través del printf incorporado:
%(datefmt)T
causes printf to output the date-time string resulting from using
datefmt as a format string for strftime(3). The corresponding argu‐
ment is an integer representing the number of seconds since the
epoch. Two special argument values may be used: -1 represents the
current time, and -2 represents the time the shell was invoked.
If no argument is specified, conversion behaves as if -1 had
been given.
This is an exception to the usual printf behavior.
Asi que,
# inner printf gets you the current unix time in seconds
# outer printf spits it out according to the format
printf "%(%Y-%m-%d)T/n" $(( $(printf "%(%s)T" -1) - 24*3600 ))
o, de manera equivalente, con una variable de temperatura (subshell externo opcional, pero mantiene las variables de entorno limpias).
(
now=$(printf "%(%s)T" -1);
printf "%(%Y-%m-%d)T/n" $((now - 24*3600));
)
Nota: a pesar de que la página de manual indica que ningún argumento para el formateador %()T
asumirá un valor por defecto de -1
, en lugar de eso, recibo un 0 (gracias, bash manual versión 4.3.48)