Uzyskaj datę ostatniego dnia ostatniego miesiąca w skrypcie powłoki

11

Jak uzyskać datę zakończenia poprzedniego miesiąca na podstawie daty przetwarzania?

Przykłady:

  • Data przetwarzania = 15jan2015
  • Oczekiwana data = 31 grudnia 2014 r.,

  • Data przetwarzania = 10 lutego 2015 r
  • Oczekiwana data = 31jan2015
użytkownik128856
źródło

Odpowiedzi:

27

Z GNU date:

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

Niektóre powłoki mają wbudowaną obsługę manipulacji datami:

Z ksh93:

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

Z 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
Stéphane Chazelas
źródło
4

Jest na to wiele sposobów ; oto najprostszy, jaki znalazłem (tutaj przy założeniu GNU date):

$ date -d "-$(date +%d) days"
Fri Jul 31 16:07:23 EDT 2015
użytkownik1717828
źródło
1
Odpowiedź @stephane jest jaśniejsza i ta nie będzie działać w dziwnych latach, w których dni były pomijane / dodawane w połowie miesiąca. Tak, to się stało. zobacz youtube.com/watch?v=-5wpm-gesOY
ctrl-alt-delor
@richard, sposób, w jaki działa przesunięcie daty GNU w dniu ( przesunięcie 1-dniowe nie jest takie samo jak przesunięcie 24-godzinne), myślę, że ta odpowiedź i moja powinny być równoważne i zawodzić tylko w strefach czasowych, które pomijałyby ostatni dzień jednego miesiąca ( zazwyczaj, gdyby to się kiedykolwiek zdarzyło, prawdopodobnie znajdowałby się na wyspie na Pacyfiku, aby przejść na przesunięcie z -12: 00 na przesunięcie o 12:00 (lub z -13 na 11 ...) ...
Stéphane Chazelas
@Stephane dziękuję za wskazanie innych problemów, czas jest trudny. Uwaga: w przypadku, gdy środek miesiąca zostanie usunięty (tak się stało), dzień 30 nie jest 30 dniem, więc odjęcie 30 nie spowoduje przejścia do ostatniego dnia poprzedniego miesiąca. Nie rozumiem, dlaczego to nie zadziała, jeśli jest pierwszy dzień miesiąca (nie jest gwarantowany). Nie oznacza to jednak, że tak będzie.
ctrl-alt-delor
@richard, patrz TZ=Pacific/Apia faketime '2011-12-31 12:00' date -d '1 day ago'. Wystąpił błąd, ponieważ nie było tam 30.12.2011. Oznacza to, że przesunięcie dnia zostało wykonane w czasie kalendarzowym. 2011-12-31 minus 31 dni daje ci 2011-11-30, ponieważ bierze 31 z 31. Nie bierze 31 * 24 * 60 * 60 * 60 sekund z bieżącego czasu. Porównaj z tym, TZ=Pacific/Apia faketime '2011-12-31 12:00' date -d '24 hour ago'co daje ci 29., czyli tym razem datę, która była 24 * 60 * 60 * 60 sekund temu.
Stéphane Chazelas,
2

Oto wersja działająca w systemie Mac OS, która korzysta z datenarzędzia BSD :

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

Argumenty są stosowane w kolejności. Możesz sobie wyobrazić, że data jest przekazywana z jednego argumentu do drugiego. Na przykład:

  • Zacznij od bieżącej daty ( date) -> 2017-03-06
  • Ustaw tę datę na 1. dzień miesiąca ( -v1d) -> 2017-03-01
  • Odejmij jeden dzień od tego ( -v-1d)-> 2017-02-28
  • Sformatuj datę ( +%d%b%Y) -> 28 lutego 2017

Możesz dotrzeć do dowolnej liczby miesięcy do przodu lub do tyłu date -v-1m -v1d -v-1d, zastępując -1mją liczbą miesięcy do tyłu lub do przodu ( +1m), którą chcesz.

To ogólna odpowiedź. To pytanie dotyczy konkretnie dat względem daty początkowej. Narzędzie daty w systemie Mac OS / BSD nie pozwala na dostarczenie znacznika danych na początek, ale każdy element daty można ustawić osobno:

date -v2015y -v1m -v15d -v1d -v-1d +%d%b%Y -> 31 grudnia 2014 r

spiffytech
źródło
0

Spróbuj użyć tego kodu

date -d "-$(date +%d) days  month" +%Y-%m-%d
Spacerować
źródło
To daje ostatni dzień tego miesiąca.
Warren Young,