2009-04-01 6 views
3

Je veux faire quelques manipulations de calendrier dans bash - spécifiquement, je veux comprendre la dernière date d'un mois donné (y compris l'année bissextile, et une préparation d'une table pour une recherche n'est pas une solution valide pour moi).Calculs du calendrier dans bash

Soi-disant que j'ai le code suivant:

$year=2009 
$start_month=2 
$end_month=10 
for $month in $(seq $start_month $end_month); do 
    echo "Last date of "$(date +"%B" -d "${year}-${month}-01")" is: " ??? 
done 

Je ne peux pas comprendre comment faire quelque chose comme ça. Je pensais que date -d fonctionnerait comme POSIX mktime et plierait les dates invalides à leurs équivalents valides, donc je pourrais dire quelque chose comme date -d "2009-03-00" et obtenir '2009-02-28', mais pas une telle chance.

Est-il possible de le faire en utilisant seulement ce qui est disponible sur bash dans un environnement GNU standard?

Répondre

6

Essayez: date -d 'yesterday 2009-03-01'

intuitif Je sais. Les versions antérieures de date utilisaient la méthode POSIX.

+0

Heh, brillant. Merci. Évidemment j'aurais dû lire la documentation d'information (pas que je vais maintenant, je ne peux pas supporter le navigateur d'informations). ' – Guss

+1

' 2009-02-01 dernier jour mois 'fonctionne également, mais c'est plus élégant. –

3

Si cela ne vous dérange pas de jouer avec grep/awk/perl, vous pouvez jeter un oeil à cal.

$ cal 4 2009 
    April 2009 
Su Mo Tu We Th Fr Sa 
      1 2 3 4 
5 6 7 8 9 10 11 
12 13 14 15 16 17 18 
19 20 21 22 23 24 25 
26 27 28 29 30 

Edit (MarkusQ): Pour expier ma solution blague ci-dessous, je vais contribuer à la vôtre:

cal 4 2009 | tr ' ' '\n' | grep -v ^$ | tail -n 1 
+1

Quelque chose comme ceci: cal 2 2009 | perl -nle 'm/\ S/et $ line = $ _; END {@r = split/\ s /, $ ligne; print pop @r; } ' Ça marcherait, je suppose, mais ce n'est pas vraiment sympa: -/ – Guss

+0

@MarkusQ: ton analyseur est beaucoup plus propre que le mien, mais je préférerais toujours la solution de Steve Baker. Merci quand même :-) – Guss

+0

cal | awk '!/^ $/{E = $ NF} FIN {print E}' – dannysauer

1

Eh bien, d'une façon serait de regarder la date actuelle dans une boucle jusqu'à ce que le mois changements de composants, enregistrement du composant de jour pour un tour. Cela vous donnerait le premier et le dernier jour du mois, mais cela pourrait être trop lent.

Posté 1 Avril 2009

+1

Ha. ce serait aussi problématique pour les dates passées, à moins que je puisse mettre la main sur une machine à voyager dans le temps. – Guss

5

date (1) 's -d est spécifique à GNU; donc utiliser ça ne marchera qu'avec GNU Linux.

Une solution plus portable (cela devrait même travailler dans sh AFAIK), est la suivante:

: $(cal 4 2009); echo $_ 
+0

Astuce soignée! définitivement "à l'extérieur de la boîte". Raison pourquoi je ne l'utiliserai pas cependant: Il produit un message d'erreur - je peux le rediriger, mais ce n'est toujours pas gentil. Aussi -d -d peut être spécifique à GNU, mais j'écris un script GNU bash - il est valide pour s'attendre à ce qu'il soit déployé sur un environnement GNU (peut aussi être Solaris) – Guss

+0

Il ne produit pas d'erreur. N'avez-vous pas mis le colon à l'avant? Ce n'est pas l'invite dans cet exemple, vous avez réellement besoin de taper deux-côlon-dollar ... etc. – camh

+1

@Guss: Il ne devrait pas y avoir de message d'erreur. Vérifiez que vous avez bien copié le message, et si c'est le cas, affichez le message d'erreur ou parlez-moi en #bash sur freenode. De plus, vous ne pouvez pas vous attendre à être dans un environnement GNU même si c'est GNU bash. Bash est disponible (même par défaut) dans beaucoup d'environnements non-GNU. – lhunath