Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Wochenberechnung mit .NET

Geschrieben von: Christoph Wille
Kategorie: .NET Allgemein

This printed page brought to you by AlphaSierraPapa

Die Frage des Tages lautet: Wie erhält man die Nummer der Woche für ein vorgegebenes Datum? Nun, die Week Funktion aus dem guten, alten VBScript gibt es nicht mehr, und auch die DateTime Klasse stellt keinerlei Methoden oder Eigenschaften zur Verfügung - wie also kommen wir wirklich vom Datum zur Woche?

Es führen wie immer viele Wege nach Rom, einige davon sind steiniger als andere. Beginnen wir also zunächst mit dem steinigsten:

public class Week {
  public static int FromDateTime(DateTime dt) 
  {
    DateTime dtFirstOfYear = new DateTime(dt.Year, 1, 1);
    int dowFirst = (int)dtFirstOfYear.DayOfWeek;
    int dowDate = (int)dt.DayOfWeek;
    
    // fix american format of week
    if (0 == dowFirst) dowFirst = 7;
    if (0 == dowDate) dowDate = 7;
    
    int nWeek = dt.DayOfYear / 7;
    
    if (0 == nWeek) {
      nWeek++;
    }
    else if (dowDate <= dowFirst) {
      nWeek++;
    }
  
    return nWeek;
  }
}

Das ist die Lösung namens "zu Fuß" - wir errechnen uns die Woche selbst mittels der DayOfWeek und of DayOfYear Eigenschaften der DateTime Klasse. Eine wichtige Angelegenheit in punkto Internationalisierung regelt die Implementierung auch noch: die Enum DayOfWeek ist amerikanisch ausgelegt, mit Sonntag als erstem Tag der Woche - dieser wird für unsere Breiten auf den letzten Tag der Woche umgestellt.

Weil wir gerade von Internationalisierung reden - gibt es da nicht den System.Globalization Namespace? Jawohl, und der hält auch eine elegante Lösung für unser Problem bereit:

  public static int InteractiveGetWeekOfYear(DateTime dt)
  {
    Calendar cal = DateTimeFormatInfo.CurrentInfo.Calendar;
    
    int nWeek = cal.GetWeekOfYear(dt,
        DateTimeFormatInfo.CurrentInfo.CalendarWeekRule,
        DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek);
    
    return nWeek;
  }

Diese Lösung wird dann verwendet, wenn man die Woche "relativ" zum interaktiven User der Applikation errechnen möchte, also zB eine Windows Forms Anwendung. Nicht gut ist dieser Ansatz, wenn die Anwendung für einen bestimmten Kulturkreis immer die gleiche Woche errechnen soll (also zB eine ASP.NET Serverapplikation). Dort "hardcodiert" man die entsprechenden Vorgaben:

  public static int AbsoluteGetWeekOfYear(DateTime dt)
  {
    GregorianCalendar cal = new GregorianCalendar();
    
    int nWeek = cal.GetWeekOfYear(dt, 
            CalendarWeekRule.FirstDay,
            DayOfWeek.Monday);
    return nWeek;
  }

Dieser Ansatz ist die beste Lösung, wenn man will, daß jeder User egal welche Ländereinstellungen er getroffen hat, immer der gleichen Wochenberechnung "ausgeliefert" ist. Grundsätzlich geht meine Empfehlung zu dieser Variante, da gerade individuelle Ländereinstellungen in internationalen Unternehmen stark verbreitet sind.

Als Abschluß noch die Anwendung der verschiedenen Ansätze:

  public static void Main(string[] args)
  {
    Console.WriteLine(Week.FromDateTime(new DateTime(2002, 1, 1))); // Tuesday
    Console.WriteLine(Week.FromDateTime(new DateTime(2002, 1, 6))); // Sunday, 1st week
    Console.WriteLine(Week.FromDateTime(new DateTime(2002, 1, 7))); // Monday, 2nd week
    Console.WriteLine(Week.FromDateTime(new DateTime(2002, 5, 20))); // Monday, 21st week
    Console.WriteLine(Week.FromDateTime(new DateTime(2002, 10, 29))); // Tuesday, 44th week
    
    Console.WriteLine(MainClass.InteractiveGetWeekOfYear(new DateTime(2002, 1, 6)));
    Console.WriteLine(MainClass.AbsoluteGetWeekOfYear(new DateTime(2002, 1, 6)));
  }

Auf meiner Maschine liefert die vorletzte Zeile die Woche 2, die letzte hingegen Woche 1. Der Grund, wie schon erwähnt sind die Ländereinstellungen des Users - bei mir US Englisch.

Schlußbemerkung

Dieser Artikel soll Ihnen kurz und prägnant vor Augen führen, welche Möglichkeiten Ihnen zur Verfügung stehen - und welche Fallstricke wie zB Ländereinstellungen der User Ihnen Probleme bereiten können.

This printed page brought to you by AlphaSierraPapa

Download des Codes

Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20020905.zip

Verwandte Artikel

Datentypen in C#
http:/www.aspheute.com/artikel/20000726.htm
Ein Touch-Utility in C#
http:/www.aspheute.com/artikel/20020226.htm
Enums lesbar machen
http:/www.aspheute.com/artikel/20010215.htm
Kontrollstatements in C#
http:/www.aspheute.com/artikel/20000714.htm
Zahl, Datum und Währung korrekt formatiert ausgeben
http:/www.aspheute.com/artikel/20020704.htm

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.