Вычтите месяцы от заданной даты в bash - PullRequest
3 голосов
/ 17 октября 2019

Я хочу вычесть месяцы из указанной даты.

businessDate='2019-12-31'
diff=1
busDate=$(date --date="$businessDate -$diff month" +%Y-%m-%d)
echo "Date: $busDate"

Этот код возвращает 2019-12-01 вместо 2019-11-30. Может кто-нибудь предложить решение, чтобы получить правильную дату?

Ответы [ 2 ]

2 голосов
/ 17 октября 2019

Как указано в «информационной дате», вычисление дат с относительным месяцем (1 месяц назад и т. Д.) Проблематично и иногда приводит к неожиданным результатам:

От: 29,7 Относительные элементы в строках даты:

Нечеткость в единицах может вызвать проблемы с относительными элементами. Например, значение «2003-07-31 -1 месяц» может быть равно 2003-07-01, поскольку 2003-06-31 является недопустимой датой

Некоторые решения:

  1. Рассматривать '1 месяц назад' как запрос на перемещение дней назад, где N - максимум (DD, дни в предыдущем месяце).
  2. Проверьте, имеет ли дата результата тот же месяц, что и исходная дата, и переместите дату на один день назад от первого дня месяца. Это необходимо для обработки перехода с марта на февраль.
  3. Альтернативный подход заключается в выполнении перемещения даты в первый день месяца (который всегда будет работать), а затем для ограничения дневной части даты, нопоследняя дата в итоговом месяце.

Преимущество третьего подхода состоит в том, что он используется для обозначения движения месяца.

Реализация варианта №3 - bash, немного громоздка, вероятно, лучше написать код Python / Perl.

IDATE=2019-12-31
N_MONTH=-1
DD_PART=$(date +'%d' -d "$IDATE")
YYYYMM=$(date +'%Y-%m' -d "$(date +'%Y-%m-01' -d "$IDATE") $N_MONTH month")
LAST_DAY_IN_YYYYMM=$(date +'%d' -d "$YYYYMM-01 +1month -1day")
if [[ "$LAST_DAY_IN_YYYYMM" -lt "$DD_PART" ]] ; then
    DD_PART=$LAST_DAY_IN_YYYYMM
fi
echo "$YYYYMM-$DD_PART"
0 голосов
/ 17 октября 2019

Во-первых, это действительно правильная дата! «2019-12-31» минус один месяц будет «2019-11-31», но поскольку у нас только 30 дней в ноябре, он отображается на 1 декабря.

Тем не менее, если вы хотите получитьнаверняка к предыдущему месяцу (думаю, это именно то, что вы хотите!), я могу предложить добавить столько дополнительных дней, сколько нужно для этого. Пожалуйста, попробуйте этот код:

businessDate='2019-12-3'
diff=1

thisMonth=$(date --date=$businessDate +%m)
extra=0 #extra days to reach the previous month for sure
while [ $(date --date="$businessDate -$diff month -$extra days" +%m) == $thisMonth ]
do
    extra=`expr $extra + 1`
done


busDate=$(date --date="$businessDate -$diff month -$extra days" +%Y-%m-%d)
echo "Date: $busDate"
...