Den letzten Tag eines Monats berechnen


Tags: ,
I like Google Plus

Der administrative Alltag mit der PowerShell wird nicht nur die großen Herausforderungen in den Themenbereichen ActiveDirectory, Exchange Server 2010, HyperV oder VMWare geprägt, sondern auch durch die vielzitierten Kleinigkeiten, über die man sich als PowerShell-Anwender, der am Anfang steht und den "Guru-Status" noch nicht erreicht hat, lange den Kopf zerbrechen kann.

Hier eine Kostprobe: Wie lässt das Datum des letzten Wochentags eines Monats ermitteln? Konkret: Welches Datum besitzt der letzte Samstag im Februar?

Um es gleich vorweg zu nehmen, es gibt wie üblich mehrere Wege das Ziel zu erreichen (eine Bing-Abfrage zu starten und die Rückgabe über eine Zerlegung des HTML zu extrahieren scheidet gleich aus). Wer die PowerShell noch nicht so gut kennt oder bereits als Software-Entwickler erfolgreich war, wird sich vielleicht für den klassisch prozeduralen Weg entscheiden und in einer Schleife die Tage des Monats vom letzten Tag beginnend bis zu Tag 1 durchlaufen (wohlwissend, dass die Schleife nie zu Ende durchlaufen wird), aus jedem Tag ein Datum bilden und dessen Wochentag mit dem gesuchten Wochentag vergleichen.

In eine function eingekleidet könnte dieser Ansatz zum Beispiel wie folgt aussehen:

function Get-LastWeekday
{
 param([Int]$Monat,[String]$Wochentag)
# Wieviele Tage hat der Monat?
 $AnzahlTageProMonat = [DateTime]::DaysInMonth(2012,$Monat)
#Alle Tage durchgehen
 for ($Tag=$AnzahlTageProMonat;$Tag-gt0;$Tag--)
 {
# Das Datum als DateTime-Wert bilden
    $Datum = Get-Date -Year 2012 -Month $Monat -Day $Tag
# Den Wochentag des Datums mit dem gesuchten Wochentag vergleichen
    if ($Datum.ToString("dddd") -eq $Wochentag)
    {
      return $Datum
    }
 }
}

Die Funktion funktioniert, sie liefert das Datum eines Wochentages, der als Name zusammen mit der Nummer eines Monats übergeben wird (als Jahreszahl wird 2012 vorausgesetzt) und sie ist aufgrund ihres prozeduralen Charaktes auf für den "Laien" halbwegs nachvollziehbar. Sie ist aber nicht unbedingt PowerShell-typisch.

Auch wenn man darüber debattieren kann, was genau PowerShell-typisch ist und ob dies unbedingt ein erstrebenswertes Ziel ist, es gibt eine deutlich kürzere Variante, die ohne Schleifen oder if-Befehl auskommt, in dem sie konsequent von der Pipeline Gebrauch macht. Diese Variante sieht wie folgt aus:

function Get-LastWeekday
{
 param([Int]$Monat,[String]$Wochentag)
# Finde das Datum vom letzten des Monats beginnend, das dem gesuchten
# Wochentag entspricht
 [DateTime]::DaysInMonth(2012,$Monat)..1 | Where-Object `
  { "$("{0:dddd}" -f (Get-Date -Year 2012 -Month $Monat -Day $_))" -eq $Wochentag } |
   Select-Object -Property @{Name="Datum";Expression={ Get-Date -Date "$_.$Monat.2012" }} -First 1
}

Ok, sie ist kürzer und eleganter (vor allem durch die Art und Weise wie die for-Schleife durch den Bereichsoperator .. ersetzt wird und das Where-Object das Foreach-Object-Cmdlet überflüssig macht), aber aufgrund verschiedener Techniken (wer die PowerShell gerade erst lernt, störrt sich erfahrungsgemäß gerne an der Variablen $_, die lediglich das aktuelle Pipeline-Objekt repräsentiert) nicht mehr so einfach nachzuvollziehen (mit den kryptischen Gebilden, die sich z.B. in Perl produzieren lassen, ist sie noch harmlos,  zumal es nicht das Ziel war die Aufgabe durch Insider-Tricks zu lösen - das obige Beispiel ist ein regulärer PowerShell-Befehl).

Auch wenn es am Ende des Tages keine Rolle spielt, wie elegant eine Lösung ist oder wie stolz der Autor auf sein Ergebnis ist, ich empfehle den "PowerShell-Weg" zu verwenden, da man dadurch mehr mit weniger Aufwand erreichen kann. Und das sollte generell das Ziel in der IT-Administration sein.

1 Kommentar

Bild von Tom C.
Tom C. (Besucher) sagt:

Schön, dass hier (weiterhin) PS-Skripte vorgestellt werden! Allerdings wäre es _SEHR_ hilfreich, wenn man die Skripte auch ein wenig kommentiert, damit der geneigte PS-Anfänger vielleicht wirklich was lernt. So weiß ich ggf. wo ich nachschauen muss, aber nicht, warum man es wie machen kann ...
Just my 2 cents

Kommentar hinzufügen

Der Inhalt dieses Feldes wird nicht angezeigt. Wenn mit Ihrer angegebenen Mail-Adresse ein Gravatar verknüpft ist, dann wird dieser neben Ihrem Kommentar eingeblendet.
  • Internet- und E-Mail-Adressen werden automatisch umgewandelt.
  • Zulässige HTML-Tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Zeilen und Absätze werden automatisch erzeugt.
  • Mail-Adressen werden im Seitenquelltext unkenntlich gemacht, um sie vor dem automatischen Erfassen durch Spammer zu schützen.

Weitere Informationen über Formatierungsoptionen