Получить дату последнего дня прошлого месяца в сценарии оболочки

11

Как получить дату окончания предыдущего месяца на основе даты обработки?

Примеры:

  • Дата обработки = 15 января 2015
  • Ожидаемая дата = 31 декабря 2014 года,

  • Дата обработки = 10 фев2015
  • Ожидаемая дата = 31 января 2015
user128856
источник

Ответы:

27

С GNU date:

$ date +%d%b%Y
16Aug2015
$ date -d "$(date +%Y-%m-01) -1 day" +%d%b%Y
31Jul2015

Некоторые оболочки имеют встроенную поддержку манипулирования датами:

С ksh93:

$ printf "%(%d%b%Y)T\n" "1st day, yesterday"
31Jul2015

С zsh:

$ zmodload zsh/datetime
$ strftime -s d %Y-%m-01-12 $EPOCHSECONDS
$ strftime -rs d %Y-%m-%d-%H $d
$ strftime %d%b%Y $((d-86400))
31Jul2015
Стефан Шазелас
источник
4

Есть много способов сделать это; вот самый простой, который я нашел (здесь предполагается, что GNU date):

$ date -d "-$(date +%d) days"
Fri Jul 31 16:07:23 EDT 2015
user1717828
источник
1
Ответ @stephane яснее, и этот не будет работать в некоторые странные годы, когда дни пропускались / добавлялись в середине месяца. Да, это случилось. см. youtube.com/watch?v=-5wpm-gesOY
ctrl-alt-delor
@richard, способ смещения даты в днях в GNU ( смещение в 1 день не совпадает с 24-часовым), я думаю, что этот и мой ответ должны быть эквивалентны и давать сбой только в часовых поясах, которые пропускают последний день одного месяца ( как правило, если это когда-нибудь случится, то, вероятно, будет на каком-то тихоокеанском острове для переключения на смещение -12: 00 к смещению на 12:00 (или от -13 до 11 ...) ...
Стефан Шазелас
@Stephane спасибо за указание на другие проблемы, время трудное. Обратите внимание, что в вашем решении, в случае удаления середины месяца (это произошло), тогда день 30 не является 30-м днем, поэтому вычитание 30 не приведет вас к последнему дню предыдущего месяца. Я не могу понять, почему это не сработает, если есть 1-й день месяца (не гарантируется). Однако это не значит, что так и будет.
Ctrl-Alt-Delor
@ Richard, видите TZ=Pacific/Apia faketime '2011-12-31 12:00' date -d '1 day ago'. Вы получаете ошибку, потому что там не было 2011-12-30. То есть смещение дня было сделано по календарному времени. 2011-12-31 минус 31 день дает вам 2011-11-30, потому что 31 снимается с 31. Это не занимает 31 * 24 * 60 * 60 * 60 секунд от текущего времени. Сравните с тем, TZ=Pacific/Apia faketime '2011-12-31 12:00' date -d '24 hour ago'что дает вам 29-е, то есть на этот раз, дату, когда это было 24 * 60 * 60 * 60 секунд назад.
Стефан Шазелас
2

Вот версия, которая работает на Mac OS, которая использует dateутилиту BSD :

date -v1d -v-1d +%d%b%Y

Аргументы применяются по порядку. Вы можете себе представить, что дата передается от одного аргумента к другому. Например:

  • Начать с текущей даты ( date) -> 2017-03-06
  • Установите эту дату на 1-й день месяца ( -v1d) -> 2017-03-01
  • Вычтите один день из этого ( -v-1d)-> 2017-02-28
  • Формат даты ( +%d%b%Y) -> 28 февраля2017

Вы можете использовать любое количество месяцев вперед или назад date -v-1m -v1d -v-1d, заменяя -1mколичество месяцев назад или вперед ( +1m) по вашему желанию.

Это общий ответ. Этот вопрос конкретно спрашивает о датах относительно даты начала. Утилита дат Mac OS / BSD не позволяет указывать дату для запуска, но вы можете установить каждый элемент даты отдельно:

date -v2015y -v1m -v15d -v1d -v-1d +%d%b%Y -> 31 декабря 2014 года

spiffytech
источник
0

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

date -d "-$(date +%d) days  month" +%Y-%m-%d
Ходить
источник
Это дает последний день этого месяца.
Уоррен Янг