En #! / Bin / bash. Comando Unix para obtener la fecha del primero de un día de la semana en un mes

8

Estoy buscando un comando directo de Unix para obtener el primer domingo del próximo mes, el primer lunes del próximo mes, el primer martes del próximo mes, el primer miércoles del próximo mes, etc.

  1. Los necesitaré en el formato de fecha completo (el tiempo no es obligatorio)

  2. Puedo obtener números como 2, 3, 4, etc. Como no quiero solo números, los necesitaré en formato de fecha (incluye día, mes, año)

    $ NEXT_MONTH=`date +'%m %Y' -d 'next month'`
    $ echo $NEXT_MONTH
    04 2017
    
    $ NEXT_SUNDAY=`cal $NEXT_MONTH | awk 'NF==7 && !/^Su/{print $1;exit}'`
    $ echo $NEXT_SUNDAY
    2
    
  3. Necesitaré estas fechas para enviar notificaciones para el grupo de correo electrónico.

Ej: podría obtener el primer sábado del próximo mes como se muestra a continuación.

$ firstofmonth=$(date -d '+1 months' '+%Y%m01')
20170401

$ firstsaturday=$(date -d "$firstofmonth" '+%Y-%m')-$((7 - \
                $(date -d "$firstofmonth" '+%u')     ))    
2017-04-1
Hima
fuente

Respuestas:

11

En ksh93:

$ printf '%(%F)T\n' 'next month, first Monday'
2017-04-03

bash, dado que 4.2 ahora admite a %(<format)Ten su printfbuitin, pero no la capacidad de analizar este tipo de expresión de fecha.

Si tuviera que usarlo bashy quisiera usarlo %(<format>)T, aún podría hacerlo sin bifurcar con algo como:

printf -v code '%(
  t=$((%s + (12 - %-H) * 60 * 60))
  increment=$((8 - %u))
  current_month=%m)T' -1
eval "$code"
until
  t=$((t + increment * 24 * 60 * 60)) # next Monday around mid-day
  printf -v code '%(date=%F month=%m)T' "$t"
  eval "$code"
  [ "$month" != "$current_month" ] # until be get to next month
do
  increment=7 # the first increment is the number of days
              # til Monday. Next increments are just a week.
done
echo "$date"
Stéphane Chazelas
fuente
#! / bin / bash. Recibo el siguiente error en bash $ printf '% (% F) T \ n' 'el próximo mes, primer lunes' -ash: printf: `(': carácter de formato no válido
Hima
1
@Hima, dije en ksh93 . bashes un clon inacabado de ksh (con algunas características de (t) csh y zsh e incluso algunas propias). Las versiones recientes de bashhan agregado soporte para printf '%(format)T'from ksh93, pero no la capacidad de analizar este tipo de especificaciones de fecha. Reemplace su she-bang con #! /path/to/ksh93 -.
Stéphane Chazelas
" bashes un clon inacabado de ksh": siempre me he sentido así.
Tim Kennedy
@Stephene, intenté con el siguiente comando para obtener el próximo mes el sábado pasado $ cal 04 2017 | awk 'NF <= 7 {print $ 6}' | grep -v "^ $" | tail -1 28 Muestra el número 28, pero estoy buscando la fecha completa 28/04/2017, por favor sugiera si es posible con él.
Hima
9

Suponiendo GNU date(para eso -dte estás usando a ti mismo), y un zshshell similar para {1..7}:

$ for i in {1..7} ; do \
    LC_ALL=C date '+%Y-%m-%d %a' -d "$(date +%Y%m0${i}) next month" ; \
  done | awk '/Mon/ {print $1}'
2017-04-03

Reemplace el awk Moncon cualquier día de la semana que sea necesario (use LC_ALL=Cpara obtener los nombres de los meses en inglés, independientemente de la configuración regional del usuario). Además, podría ser mejor almacenar esto en una variable si va a volver a consultar para cada día de la semana:

$ days=$(for i in {1..7} ; do \
           LC_ALL=C date '+%Y-%m-%d %a' -d "$(date +%Y%m0${i}) next month" ; \
         done)

$ for i in Mon Tue Wed Thu Fri Sat Sun ; do \
    echo "${days}" | awk "/${i}/"'{print $1}' ; \
  done
2017-04-03
2017-04-04
2017-04-05
2017-04-06
2017-04-07
2017-04-01
2017-04-02
parkamark
fuente
En bash también, este código devuelve el próximo mes primero dom, lunes, miércoles, por lo tanto, viernes, sábado. Gracias. Creo que puedo modificar este comando para obtener el próximo mes el último domingo, lunes, miércoles, etc. Permítanme probar esto.
Hima
Hola, probé el siguiente comando para obtener el próximo mes el sábado pasado $ cal 04 2017 | awk 'NF <= 7 {print $ 6}' | grep -v "^ $" | cola -1 Muestra el número 28, pero estoy buscando la fecha completa como 28/04/2017, por favor sugiera si es posible.
Hima
"para i en {1..7}; fecha '+% Y-% m-% d% a' -d" $ (fecha +% Y% m01 -d '2 meses') $ {i} días atrás "; done | awk '/ Sat / {print $ 1}'" - esto dará 2017-04-29, que es el último sábado del próximo mes. Este código avanza 2 meses, hasta el primer día de ese mes, y luego retrocede de 1 a 7 días para obtener los datos de los últimos 7 días del mes anterior. Yo personalmente evitaría usar cal ya que he probado los otros ejemplos aquí y ninguno funciona en mi versión (CentOS 6).
parkamark
2

PHP en realidad hace que sea bastante fácil analizar fechas con entrada de texto, si está disponible en su sistema.

Ejemplo:

bash-[522]$ php -qr 'date_default_timezone_set("UTC"); echo date("d-m-Y\n", strtotime("first monday of next month"));'
03-04-2017

Tengo esta función en mi .bashrc:

get_date ()
{
    text="$*";
    php -qr "date_default_timezone_set(\"UTC\"); echo date(\"d-m-Y\n\", strtotime(\"$text\"));"
}

Que puedo usar como:

bash-[523]$ get_date first monday of next month
03-04-2017

Opción Editar Añadir para usarcal

Casi todos los sistemas que tenga bashtendrán cal. El programa del calendario. Usted puede obtener una lista de la fecha de la primera semana de cada día mediante la ejecución de una combinación de cal, datey awk, de la siguiente manera:

 cal -hN $(date -d 'next month' +%b' '%Y) | grep -v $(date -d 'next month' +%b) | awk -v date=$(date -d 'next month' +%Y-%m-) '{ printf "%s: "date"%02i\n", $1, $2; }'

Lo que te dará el siguiente resultado:

Su: 2017-04-02
Mo: 2017-04-03
Tu: 2017-04-04
We: 2017-04-05
Th: 2017-04-06
Fr: 2017-04-07
Sa: 2017-04-01

Cambie $2a $NFen la declaración awk para obtener la fecha de la última ocurrencia de cada día en un mes.

Tim Kennedy
fuente
No funciona en bash, $ php -qr 'date_default_timezone_set ("UTC"); echo date ("dmY \ n", strtotime ("primer lunes del próximo mes")); ' -bash: php: comando no encontrado. por favor, hágame saber la forma de hacerlo también en bash. y también, el comando para obtener el próximo mes el último domingo hasta el sábado. Lo intenté, de alguna manera arroja errores. Gracias ..!!
Hima
Los medios que no tienes phpinstalados. He puesto al día con un ejemplo que utiliza los cal, datey awklos comandos.
Tim Kennedy
Intenté este comando y arroja un error. Gracias.!! $ cal -hN $ (fecha -d 'próximo mes' +% b ''% Y) | grep -v $ (fecha -d 'próximo mes' +% b) | awk -v date = $ (date -d 'next month' +% Y-% m-) '{printf "% s:" date "% 02i \ n", $ 1, $ 2; } 'cal: opción no válida - uso h: cal [-13smjyV] [[mes] año]
Hima