Obtenez la date du dernier jour du mois dernier dans un script shell

11

Comment obtenir la date de fin du mois précédent, en fonction de la date de traitement?

Exemples:

  • Date de traitement = 15jan2015
  • Date prévue = 31déc2014,

  • Date de traitement = 10fév2015
  • Date prévue = 31jan2015
user128856
la source

Réponses:

27

Avec GNU date:

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

Certains shells ont un support intégré pour la manipulation de date:

Avec ksh93:

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

Avec 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
la source
4

Il existe de nombreuses façons de procéder; voici la plus simple que j'ai trouvée (en supposant ici GNU date):

$ date -d "-$(date +%d) days"
Fri Jul 31 16:07:23 EDT 2015
user1717828
la source
1
La réponse de @stephane est plus claire, et celle-ci ne fonctionnera pas dans certaines années étranges, où les jours ont été ignorés / ajoutés au milieu du mois. Oui, c'est arrivé. voir youtube.com/watch?v=-5wpm-gesOY
ctrl-alt-delor
@richard, la façon dont les décalages de jour de date GNU fonctionnent (un décalage de 1 jour n'est pas le même que celui de 24 heures), je pense que cette réponse et la mienne devraient être équivalentes et échouer uniquement dans les fuseaux horaires qui ignoreraient le dernier jour d'un mois ( typiquement, si cela arrivait, ce serait probablement dans une île du Pacifique pour passer à -12: 00 offset à 12:00 offset (ou -13 à 11 ...) ...
Stéphane Chazelas
@Stephane merci d'avoir signalé d'autres problèmes, le temps est difficile. Notez dans votre solution, dans le cas où le milieu du mois est supprimé (ce qui est arrivé), alors le jour 30 n'est pas le 30e jour, donc la soustraction de 30 ne vous amènera pas au dernier jour du mois précédent. Je ne vois pas pourquoi celui-ci ne fonctionnera pas, s'il y a un 1er jour du mois (non garanti). Cependant, cela ne signifie pas que ce sera le cas.
ctrl-alt-delor
@richard, Voir TZ=Pacific/Apia faketime '2011-12-31 12:00' date -d '1 day ago'. Vous obtenez une erreur car il n'y avait pas de 2011-12-30. Autrement dit, le décalage du jour a été effectué sur l'heure du calendrier. Le 31/12/2011 moins 31 jours vous donne le 30/11/2011 car il en prend 31 de moins 31. Il ne prend pas 31 * 24 * 60 * 60 * 60 secondes de l'heure actuelle. Comparez avec TZ=Pacific/Apia faketime '2011-12-31 12:00' date -d '24 hour ago'qui vous donne le 29, c'est-à-dire cette fois la date à laquelle il y a 24 * 60 * 60 * 60 secondes.
Stéphane Chazelas
2

Voici une version qui fonctionne sur Mac OS, qui utilise l' dateutilitaire BSD :

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

Les arguments sont appliqués dans l'ordre. Vous pouvez en quelque sorte imaginer qu'une date est transmise d'un argument à l'autre. Par exemple:

  • Commencez par la date actuelle ( date) -> 2017-03-06
  • Fixez cette date au 1er jour de son mois ( -v1d) -> 2017-03-01
  • Soustrayez un jour de cela ( -v-1d)-> 2017-02-28
  • Formater la date ( +%d%b%Y) -> 28fév2017

Vous pouvez atteindre n'importe quel nombre de mois en avant ou en arrière en utilisant date -v-1m -v1d -v-1d, en remplaçant -1mpar le nombre de mois en arrière ou en avant ( +1m) que vous souhaitez.

Voilà la réponse générique. Cette question porte spécifiquement sur les dates par rapport à une date de début. L'utilitaire de date Mac OS / BSD ne vous permet pas de fournir un horodatage pour commencer, mais vous pouvez définir chaque élément de date individuellement:

date -v2015y -v1m -v15d -v1d -v-1d +%d%b%Y -> 31déc2014

spiffytech
la source
0

Essayez d'utiliser ce code

date -d "-$(date +%d) days  month" +%Y-%m-%d
Marcher
la source
Cela donne le dernier jour de ce mois.
Warren Young