Как использовать bash для получения последнего дня каждого месяца для текущего года без использования if else или switch или while loop?

Как мы знаем, каждый год каждый следующий месяц должен иметь следующий максимальный день:

Jan - 31 days
Feb - 28 days / 29 days (leap year)
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days

Как мне получить bash для возврата значения (последний день каждого месяца) за текущий год без использования циклов if else или switch или while?

Ответ 1

мой прием:

for m in {1..12}; do
  date -d "$m/1 + 1 month - 1 day" "+%b - %d days"; 
done

Чтобы объяснить: для первой итерации, когда m = 1, аргумент -d равен "1/1 + 1 месяц - 1 день" и "1/1" интерпретируется как 1 января. Итак, 1 января + 1 месяц - 1 день - 31 января. Следующая итерация "2/1" - 1 февраля, добавьте месяц, чтобы вычесть день, чтобы получить 28 или 29 февраля. И так далее.

Ответ 2

cat <<EOF
Jan - 31 days
Feb - `date -d "yesterday 3/1" +"%d"` days
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days
EOF

Ответ 3

Предполагая, что вы разрешаете "для", затем следующее в bash

for m in {1..12}; do
    echo $(date -d $m/1/1 +%b) - $(date -d "$(($m%12+1))/1 - 1 days" +%d) days
done

производит это

 Jan - 31 days
 Feb - 29 days
 Mar - 31 days
 Apr - 30 days
 May - 31 days
 Jun - 30 days
 Jul - 31 days
 Aug - 31 days
 Sep - 30 days
 Oct - 31 days
 Nov - 30 days
 Dec - 31 days

Примечание. Я удалил необходимость cal

Для тех, кто любит мелочи:

Number months from 1 to 12 and look at the binary representation in four
bits {b3,b2,b1,b0}.  A month has 31 days if and only if b3 differs from b0.
All other months have 30 days except for February.

Итак, за исключением февраля это работает:

for m in {1..12}; do
    echo $(date -d $m/1/1 +%b) - $((30+($m>>3^$m&1))) days
done

Результат:

Jan - 31 days
Feb - 30 days (wrong)
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days
Dec - 31 days

Ответ 4

cal $(date +"%m %Y") | awk 'NF {DAYS = $NF}; END {print DAYS}'

Ответ 5

возвращает количество дней в месяце, компенсирующих февральские изменения в високосные годы без цикла или использования оператора if и только один раз называет дату.

Этот код проверяет дату, чтобы увидеть, действительно ли 29 февраля запрошенного года, если это так, то он обновляет второй символ в строке смещения дня. Аргумент месяца выбирает соответствующую подстроку и добавляет разницу в месяц к 28.

function daysin()
{
   s="303232332323"                                        # normal year
   date -d "2/29/$2" > /dev/null 2>&1 && s="313232332323"  # leap year
   echo $[ ${s:$[$1-1]:1} + 28 ]
}

daysin $1 $2                                               #daysin [1-12] [YYYY]

Ответ 6

Попробуйте использовать этот код

date -d "-$(date +%d) days  month" +%Y-%m-%d

Ответ 7

Содержание script.sh:

#!/bin/bash
begin="-$(date +'%-m') + 2"
end="10+$begin"

for ((i=$begin; i<=$end; i++)); do
    echo $(date -d "$i month -$(date +%d) days" | awk '{ printf "%s - %s days", $2, $3 }')
done

Результаты:

Jan - 31 days
Feb - 29 days
Mar - 31 days
Apr - 30 days
May - 31 days
Jun - 30 days
Jul - 31 days
Aug - 31 days
Sep - 30 days
Oct - 31 days
Nov - 30 days

Ответ 8

На Mac, который показывает дату BSD, вы можете просто:

for i in {2..12}; do date -v1d -v"$i"m -v-1d "+%d"; done

Быстрое пояснение

-v означает настройку. Мы корректируем дату:

-v1d означает первый день месяца

-v"$i"m определен месяц, например. (-v2m за февраль)

-v-1d минус один день (так что мы получаем последний день предыдущего месяца)

"+%d" распечатать день месяца

for i in {2..12}; do date -v1d -v"$i"m -v-1d "+%d"; done
31
28
31
30
31
30
31
31
30
31
30

Вы можете добавить год, конечно. См. Примеры в man-странице (ссылка выше).

Ответ 9

for m in $(seq 1 12); do cal  $(date +"$m %Y") | grep -v "^$" |tail -1|grep -o "..$"; done
  • итерация от 1 до 12 (для...)
  • распечатать таблицу календаря для каждого месяца (cal...)
  • удалить пустые строки из вывода (grep -v...)
  • напечатать последний номер в таблице (хвост...)

Нет смысла избегать использования cal, потому что это требуется POSIX, поэтому должно быть там