Sukram: C-Sharp Kalenderwoche

Hallo,

ich habe bis jetzt nur C programmiert und muss "zwangsweise" einen Ausflug in C-Sharp machen. Jetzt stehe ich da vor einem kleine Problem:

  
using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
  
  
namespace ConsoleApplication1  
{  
    class Program  
    {  
        public static CalendarWeek GetGermanCalendarWeek(DateTime date)  
        {  
            double a = Math.Floor((14 - (date.Month)) / 12D);  
            double y = date.Year + 4800 - a;  
            double m = (date.Month) + (12 * a) - 3;  
  
            double jd = date.Day + Math.Floor(((153 * m) + 2) / 5) +  
               (365 * y) + Math.Floor(y / 4) - Math.Floor(y / 100) +  
               Math.Floor(y / 400) - 32045;  
  
            double d4 = (jd + 31741 - (jd % 7)) % 146097 % 36524 %  
               1461;  
            double L = Math.Floor(d4 / 1460);  
            double d1 = ((d4 - L) % 365) + L;  
  
            // Kalenderwoche ermitteln  
            int calendarWeek = (int)Math.Floor(d1 / 7) + 1;  
  
            // Das Jahr der Kalenderwoche ermitteln  
            int year = date.Year;  
            if (calendarWeek == 1 && date.Month == 12)  
                year++;  
            if (calendarWeek >= 52 && date.Month == 1)  
                year--;  
  
            // Die ermittelte Kalenderwoche zurückgeben  
            return new CalendarWeek(year, calendarWeek);  
        }  
        static void Main(string[] args)  
        {  
            System.Console.WriteLine("Hallo Welt!");  
        }  
    }  
  
  
}  

Ich möchte ganz gerne die aktuelle Kalendwerwoche ermitteln und in Main anstatt "Hallo Welt" zurückgeben. In der aktuellen Konstellation gibt er mir den Fehler: "Der Typ- oder Namespacename "CalendarWeek" konnte nicht gefunden werden. (Fehlt eine using-Direktive oder ein Assemblyverweis?)
The type or namespace name 'type/namespace' could not be found (are you missing a using directive or an assembly reference?)"
Wie wird dieser Fehler behoben und wie muss ich die Funktion ansprechen?

  1. Hi!

    class Program

    Das ist deine einzige Klasse (die du hier vorgestellt hast).

    public static CalendarWeek GetGermanCalendarWeek(DateTime date)

    Die hat eine statische Methode namens GetGermanCalendarWeek. Der Rückgabewert soll CalendarWeek sein, diesen Typ hast du aber nicht deklariert. Oder aber der Code dazu liegt in einer anderen Datei und/oder einem anderen Namespace, von dem du nichts erwähnt hast und die nicht gefunden/eingebunden wurde. Den Typ braucht es eigentlich auch gar nicht, weil ein Integer-Wert vom Informationsgehalt ausreicht.

    // Die ermittelte Kalenderwoche zurückgeben
                return new CalendarWeek(year, calendarWeek);

    Hier erstellst du ein neues Objekt vom nicht existierenden Typ CalendarWeek, dessen Konstruktor zwei Werte übernehmen soll. Wenn du wirklich ein Objekt mit zwei Eigenschaften haben möchtest, dann musst du zunächst die Struktur (oder vielleicht auch Klasse) CalendarWeek erstellen (oder bekanntgeben).

    Ich möchte ganz gerne die aktuelle Kalendwerwoche ermitteln und in Main anstatt "Hallo Welt" zurückgeben. In der aktuellen Konstellation gibt er mir den Fehler: "Der Typ- oder Namespacename "CalendarWeek" konnte nicht gefunden werden. (Fehlt eine using-Direktive oder ein Assemblyverweis?)

    Kommt darauf an ob der fehlende Typ CalendarWeek in einem anderen Namespace liegt oder nicht.

    The type or namespace name 'type/namespace' could not be found (are you missing a using directive or an assembly reference?)"
    Wie wird dieser Fehler behoben und wie muss ich die Funktion ansprechen?

    (Man spricht bei C# von Methoden.) Wo genau liegt dein Problem mit der Methode? Ansonsten: Name hinschreiben, Klammer auf, Parameter, Klammer zu.

    Lo!

    1. Hallo, anscheinend fehlt mir dazu einfach noch das Grundverständnis. Nichts desto trotz muss ich das irgendwie hinbekommen. Das Ganze habe ich von folgenden Artikeln zusammengeklaubt:

      http://books.google.de/books?id=p--ZBLrQMRAC&lpg=PA165&ots=VWogFsL9mK&dq=c sharp kalenderwoche&pg=PA161#v=onepage&q=&f=false
      http://dotnet-snippets.de/dns/kalenderwoche-berechnen-SID260.aspx

      Nun möchte ich, wie schon geschrieben, dass ich die aktuelle Kalenderwoche ermittele. Kann mir dazu jmd. ein fertiges Snippet liefern?

      1. Yerf!

        Nun möchte ich, wie schon geschrieben, dass ich die aktuelle Kalenderwoche ermittele. Kann mir dazu jmd. ein fertiges Snippet liefern?

        Hast du doch im Prinzip schon, du musst sie nur vollständig abtippen. Über der Methode steht in bei den verlinkten Beispielen jeweils noch die CalendarWeek-Klasse, die brauchst du auch dazu.

        Gruß,

        Harlequin

        --
        RIP --- XHTML 2
        nur die Besten sterben jung
        1. Yerf!

          Nun möchte ich, wie schon geschrieben, dass ich die aktuelle Kalenderwoche ermittele. Kann mir dazu jmd. ein fertiges Snippet liefern?

          Hast du doch im Prinzip schon, du musst sie nur vollständig abtippen. Über der Methode steht in bei den verlinkten Beispielen jeweils noch die CalendarWeek-Klasse, die brauchst du auch dazu.

          Gruß,

          Harlequin

          Ok,

          als Grundgerüst habe ich:

            
          using System;  
          using System.Collections.Generic;  
          using System.Linq;  
          using System.Text;  
            
          namespace ConsoleApplication1  
          {  
            
                 class Program  
              {  
                  static void Main(string[] args)  
                  {  
                      System.Console.WriteLine("Hallo Welt!");  
                  }  
              }  
            
            
          }  
          
          

          Als Snippet habe ich:

            
          public class DateUtils  
          {  
             /// <summary>  
             /// Verwaltet die Daten einer Kalenderwoche  
             /// </summary>  
             public class CalendarWeek  
             {  
                /// <summary>  
                /// Das Jahr  
                /// </summary>  
                public int Year;  
            
                /// <summary>  
                /// Die Kalenderwoche  
                /// </summary>  
                public int Week;  
            
                /// <summary>  
                /// Konstruktor  
                /// </summary>  
                /// <param name="year">Das Jahr</param>  
                /// <param name="week">Die Kalenderwoche</param>  
                public CalendarWeek(int year, int week)  
                {  
                   this.Year = year;  
                   this.Week = week;  
                }  
             }  
            
             /// <summary>  
             /// Berechnet die Kalenderwoche eines internationalen Datums  
             /// </summary>  
             /// <param name="date">Das Datum</param>  
             /// <returns>Gibt ein CalendarWeek-Objekt zurück</returns>  
             /// <remarks>  
             /// Diese Methode berechnet die Kalenderwoche eines Datums  
             /// nach der GetWeekOfYear-Methode eines Calendar-Objekts  
             /// und korrigiert den darin enthaltenen Fehler.  
             /// </remarks>  
             public static CalendarWeek GetCalendarWeek(DateTime date)  
             {  
                // Aktuelle Kultur ermitteln  
                CultureInfo currentCulture = CultureInfo.CurrentCulture;  
            
                // Aktuellen Kalender ermitteln  
                Calendar calendar = currentCulture.Calendar;  
            
                // Kalenderwoche über das Calendar-Objekt ermitteln  
                int calendarWeek = calendar.GetWeekOfYear(date,  
                   currentCulture.DateTimeFormat.CalendarWeekRule,  
                   currentCulture.DateTimeFormat.FirstDayOfWeek);  
            
                // Überprüfen, ob eine Kalenderwoche größer als 52  
                // ermittelt wurde und ob die Kalenderwoche des Datums  
                // in einer Woche 2 ergibt: In diesem Fall hat  
                // GetWeekOfYear die Kalenderwoche nicht nach ISO 8601  
                // berechnet (Montag, der 31.12.2007 wird z. B.  
                // fälschlicherweise als KW 53 berechnet).  
                // Die Kalenderwoche wird dann auf 1 gesetzt  
                if (calendarWeek > 52)  
                {  
                   date = date.AddDays(7);  
                   int testCalendarWeek = calendar.GetWeekOfYear(date,  
                      currentCulture.DateTimeFormat.CalendarWeekRule,  
                      currentCulture.DateTimeFormat.FirstDayOfWeek);  
                   if (testCalendarWeek == 2)  
                      calendarWeek = 1;  
                }  
            
                // Das Jahr der Kalenderwoche ermitteln  
                int year = date.Year;  
                if (calendarWeek == 1 && date.Month == 12)  
                   year++;  
                if (calendarWeek >= 52 && date.Month == 1)  
                   year--;  
            
                // Die ermittelte Kalenderwoche zurückgeben  
                return new CalendarWeek(year, calendarWeek);  
             }  
            
            
             /// <summary>  
             /// Berechnet die Kalenderwoche eines deutschen Datums  
             /// </summary>  
             /// <param name="date">Das Datum</param>  
             /// <returns>Gibt ein CalendarWeek-Objekt zurück</returns>  
             /// <remarks>  
             /// <para>  
             /// Diese Methode gilt nur für die deutsche Kultur.  
             /// Sie ist wesentlich schneller als die Methode  
             /// <see cref="GetInternationalCalendarWeek"/>.  
             /// </para>  
             /// <para>  
             /// Die Berechnung erfolgt nach dem  
             /// C++-Algorithmus von Ekkehard Hess aus einem Beitrag vom  
             /// 29.7.1999 in der Newsgroup  
             /// borland.public.cppbuilder.language  
             ///(freigegeben zur allgemeinen Verwendung)  
             /// </para>  
             /// </remarks>  
             public static CalendarWeek GetGermanCalendarWeek(DateTime date)  
             {  
                double a = Math.Floor((14 - (date.Month)) / 12D);  
                double y = date.Year + 4800 - a;  
                double m = (date.Month) + (12 * a) - 3;  
            
                double jd = date.Day + Math.Floor(((153 * m) + 2) / 5) +  
                   (365 * y) + Math.Floor(y / 4) - Math.Floor(y / 100) +  
                   Math.Floor(y / 400) - 32045;  
            
                double d4 = (jd + 31741 - (jd % 7)) % 146097 % 36524 %  
                   1461;  
                double L = Math.Floor(d4 / 1460);  
                double d1 = ((d4 - L) % 365) + L;  
            
                // Kalenderwoche ermitteln  
                int calendarWeek = (int)Math.Floor(d1 / 7) + 1;  
            
                // Das Jahr der Kalenderwoche ermitteln  
                int year = date.Year;  
                if (calendarWeek == 1 && date.Month == 12)  
                   year++;  
                if (calendarWeek >= 52 && date.Month == 1)  
                   year--;  
            
                // Die ermittelte Kalenderwoche zurückgeben  
                return new CalendarWeek(year, calendarWeek);  
             }  
          }  
          
          

          Wo muss ich das Snippet in das Grundgerüst einfügen (und muss ich evtl. noch using System.Globalization einfügen etc.) und wie rufe ich das Ganze dann auf?

          1. Hi!

            Wo muss ich das Snippet in das Grundgerüst einfügen

            Am besten gar nicht. Das verbietet sich aus Gründen der Wiederverwendbarkeit. Eine Assembly wäre da geeigneter. Aber ich will es mal für den Moment nicht übertreiben. Erstell eine neue Datei für die Klasse DateUtils. Wenn die im gleichen Projekt wie Program liegt, ist nichts weiter zu machen.

            (und muss ich evtl. noch using System.Globalization einfügen etc.)

            Wenn du mit einem Wuschel Studio arbeitest, solltest du schon an der Färbung von CultureInfo sehen, dass da was nicht stimmt. Cursor drauf stellen und über den kleinen erscheinenden Knubbel kannst du den benötigten using-Verweis einfügen lassen.

            und wie rufe ich das Ganze dann auf?

            Das ist Grundlagenwissen. Wenn es dir daran fehlt, bemüh bitte ein Tutorial. Bei fehlendem Detailwissen, sag, was du bisher hast und wo es konkret hängt. Das Ergebnis der Methode solltest du jedenfalls in einer Variablen ablegen, weil du beide Werte (Woche und Jahr) benötigen wirst. Der Rest ist String-Verknüpfung oder besser noch Format-String mit Platzhaltern (das kann man auch mit Console.Write("... {0} ... {1} ...", wert1, wert2)).

            Lo!

            1. Hallo,

              ich die Klasse nun in einer extra Datei laufen und auch den richtige using-Verweis laufen. Jetzt hänge ich nur noch an dem Aufruf der Klasse. Wäre nett, wenn mir da jmd hilft. Wie schon geschrieben kenne ich mich mehr in C aus (also nicht objektorientiert).

              Jetzt mal so mehr oder weniger aus dem Bauch heraus würde ich für den Anfang so etwas in der Richtung vermuten:

                
              DateUtils kw= new DateUtils.CalendarWeek();  
              
              

              Wie übergebe ich als Paramter das aktuelle Datum?

              1. Hi!

                ich die Klasse nun in einer extra Datei laufen und auch den richtige using-Verweis laufen. Jetzt hänge ich nur noch an dem Aufruf der Klasse. Wäre nett, wenn mir da jmd hilft. Wie schon geschrieben kenne ich mich mehr in C aus (also nicht objektorientiert).

                Zum besseren Verständnis wiederhole ich mal deinen jetzigen Code-Aufbau.

                namespace ConsoleApplication1
                  class Program
                    static void Main(string[] args)

                namespace ConsoleApplication1 // [*]
                  public class DateUtils
                    public class CalendarWeek
                      public int Year;
                      public int Week;
                      public CalendarWeek(int year, int week)

                public static CalendarWeek GetCalendarWeek(DateTime date)
                    public static CalendarWeek GetGermanCalendarWeek(DateTime date)

                Du schachtelst da die CalenderWeek-Klasse [**] in die DateUtils. Das kann man machen, aber gerade als Anfänger würde ich das nicht empfehlen. Da bekommst du nur noch eine Namens-Ebene hinzu ohne groß was zu gewinnen. Du musst den Typ nämlich im nicht zur DateUtils-Klasse gehörenden Code nun immer als DateUtils.CalendarWeek ansprechen. Ich würde das nur dann so schachteln, wenn es sich um einen wenig bedeutenden und nur im Zusammenhang mit der äußeren Klasse sinnvoll zu verwendenden Typ handelt. Aber das ist nur nebensächlich.

                Die beiden Methoden GetCalendarWeek und GetGermanCalendarWeek unterscheiden sich nur innerlich, weswegen hier die Betrachtung auf GetCalendarWeek eingeschränkt werden kann. Statische Methoden ruft man mit dem Klassennamen gefolgt vom Methodennamen auf, in dem Fall also DateUtils.GetCalendarWeek(). Als Parameter muss noch ein DateTime-Wert übergeben werden. Das ist nichts besonderes, denn das geht genau so wie bei der herkömmlichen Programmierung.

                [*] Angenommenerweise ist es der selbe Namespace. Ansonsten braucht das Hauptprogramm noch ein using auf diesen Namespace.
                [**] struct (ein Werttyp - Value Type) fände ich angebrachter als class (ein Verweistyp - Reference Type). Es werden nur Werte gepeichert und die Möglichkeiten einer Klasse weder genutzt noch benötigt. Vergleiche mit DateTime, das ist auch nur struct und nicht class.

                Jetzt mal so mehr oder weniger aus dem Bauch heraus würde ich für den Anfang so etwas in der Richtung vermuten:
                DateUtils kw= new DateUtils.CalendarWeek();

                Nein. Versuch dir bitte selbst zu erklären, was du mit dem jeweiligen Element bezweckst, das du da notiert hast.

                Der Ergebnis soll eine CalendarWeek-Struktur/Klasse sein. Also brauchst du eine Variable eines solchen Typs. CalenderWeeks ist derzeit eine Unterklasse von DateUtils, also lautet die Typbezeichnung: DateUtils.CalendarWeek
                Und dann möchtest du das Ergebnis der Methode GetCalendarWeek() (oder die andere) darin ablegen. GetCalendarWeek ist als statische Methode angelegt, also ... siehe oben.

                Wie übergebe ich als Paramter das aktuelle Datum?

                Schau dir die Struktur DateTime genauer an. Die hat eine Eigenschaft namens Now.

                Mein Lösungsweg wäre übrigens ein anderer und käme nur mit der Struktur CalendarWeek aus. Der gäbe ich neben den beiden Eigenschaften und dem Konstruktor die statische Methode GetFromDate() auf den Weg und zwar mit den beiden Signaturen

                CalendarWeek GetFromDate(DateTime date)
                  CalendarWeek GetFromDate(DateTime date, bool german)

                Lo!

                1. Supi, jetzt komme ich dem Ganzen so langsam dahinter.
                  Vielen Dank für die Erklärung.
                  Ich habe jetzt einfach mal eine Ausgabe geschrieben:

                    
                  Console.WriteLine("{0}", DateUtils.GetCalendarWeek(DateTime.Now).Week);  
                  Console.WriteLine("{0}", DateUtils.GetCalendarWeek(DateTime.Now).Year);  
                  
                  

                  Gruß

                  sukram

                  1. Hi!

                    Console.WriteLine("{0}", DateUtils.GetCalendarWeek(DateTime.Now).Week);
                    Console.WriteLine("{0}", DateUtils.GetCalendarWeek(DateTime.Now).Year);

                    So ist das aber uneffizient, weil die Berechnung zweimal stattfinden muss. Und wenn das eine lange laufende Berechnung wäre, hättest du auch noch zwei verschiedene Now-Werte. Besser ist das Ergebnis einmal zu berechnen und in einer Variablen (vom Typ DateUtils.CalendarWeek) abzulegen. Außerdem ist die Platzhalter-Schreibweise erst dann sinnvoll, wenn mehr als nur ein Wert auszugeben ist.

                    DateTime date = DateTime.Now;
                    DateUtils.CalendarWeek cw = DateUtils.GetCalendarWeek(date);
                    Console.WriteLine("Der {0:d} gehört zur Woche {1} des Jahres {2}", date, cw.Week, cw.Year);

                    Lo!

                    1. DateTime date = DateTime.Now;
                      DateUtils.CalendarWeek cw = DateUtils.GetCalendarWeek(date);
                      Console.WriteLine("Der {0:d} gehört zur Woche {1} des Jahres {2}", date, cw.Week, cw.Year);

                      Ok, vielen Dank. Das habe ich verstanden.

                      Gruß

                      sukram

      2. Hi!

        Nun möchte ich, wie schon geschrieben, dass ich die aktuelle Kalenderwoche ermittele. Kann mir dazu jmd. ein fertiges Snippet liefern?

        Ich tät einfach die Klasse CalendarWeek ganz weglassen (außerdem hätte es eine Struktur auch getan) und einfach nur die Wochennummer als Integerwert zurückgeben. Und das wäre dann so einfach, dass ich dazu kein Snippet liefere, denn das ist Grundlagenwissen.

        Lo!

        1. Hi!

          Ich tät einfach die Klasse CalendarWeek ganz weglassen (außerdem hätte es eine Struktur auch getan) und einfach nur die Wochennummer als Integerwert zurückgeben.

          ... mit dem Ergebnis, das um den Jahreswechsel rum falsche Ergebnisse entstehen. Man braucht doch das Jahr dazu. Der erste bis dritte Januar kann ja auch in Woche 52 des Vorjahres liegen.

          Sukram: Also einfach nur den Code richtig kopieren. Und wenn du beim Anwenden der Methode Probleme hast, dann benenn diese bitte.

          Lo!