Entwickler-Ecke

Basistechnologien - Gedankenproblem beim Datumsvergleich


coolace - Mo 01.09.08 14:12
Titel: Gedankenproblem beim Datumsvergleich
Hy,

ich habe folgendes Problem, ich habe eine List<daten> erstellt und ich möchte aus dieser Liste
das nächste Geburtstagskind herausfinden. Die Liste ist sortiert. Aber irgendwie klappt das unten nicht
so ganz mit der Ausgabe der richtigen nächsten Person


C#-Quelltext
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:
 DateTime aktuell = DateTime.Now;
            foreach (daten temps in liste)
            {
                lbox.Items.Add(temps.ToString());
            }
            
            foreach (daten tempi in liste)
            {

              if (tempi.Gebdatum.Month >= aktuell.Month)
               {
                   
                  
                  for (int i = 0; i < liste.Count; i++)
                   {
                       if (tempi.Gebdatum.Day < liste[i].Gebdatum.Day && liste[i].Gebdatum.Month > aktuell.Month)
                       {
                           txtage.Text = tempi.Alter();
                           txtgeburtstag.Text = tempi.Gebname; 
                       } 
                   }
                   
                 
               }
                       
                
            }


Danke und Gruß

Coolace


Kha - Mo 01.09.08 14:20

"Irgendwie" ist nie eine gute Fehlerbeschreibung.
Du kannst zwei DateTimes direkt miteinander vergleichen, die innere Schleife brauchst du also gar nicht. Außerdem macht es wohl keinen Sinn, nach einem Treffer die Suche fortzusetzen ;).


coolace - Mo 01.09.08 14:28

Sorry, das Problem ist das wenn andere datums dazwischen sind ich dann auf die Monate zurückgreifen muss

z.B.
02.04.1955 detlef
08.02.1963 anna
09.10.1973 fred
14.07.1984 anna2
14.10.1986 diem
10.10.1990 fred


in dieser sortierten Liste währe 09.10.1973 fred der richtige Geburtstagskandidat aber dies klappt nicht er nimmt lieber
den letzen fred her.

darum dachte ich ich vergleich erstmal alle in der Liste mit dem aktuellen Monat, größer oder gleich, danach war der
Gedanke brauch für die richtige Person wenn mehrere im selben Monat geburtstag haben ja immer den mit dem kleinsten Tag.

Das klappt nicht,


coolace - Mo 01.09.08 16:16

Hy,

hab die geschichte mal aus einem frühreren Thread versucht anzupassen


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
daten naechster = null;
            DateTime aktuell = DateTime.Now;
            foreach (daten temps in liste)
            {
                lbox.Items.Add(temps.ToString());
            }
            
                                       
             for (int i = 0; i < liste.Count; i++)
              {
                 //Geburtstage im aktuellen Jahr 
                 DateTime compare = new DateTime(aktuell.Year,liste[i].Gebdatum.Month, liste[i].Gebdatum.Day);
                 if ((compare.CompareTo(aktuell) >= 0) && (aktuell - compare) < (aktuell - naechster.Gebdatum) /*näher dran als der bisher "beste" */)
                     naechster = liste[i];
              }             
            
            txtage.Text = naechster.Alter();
            txtgeburtstag.Text = naechster.Gebname;
        }


aber irgendwo ist hier noch ein Gedankenfehler, er zeigt gar nichts an?

LG

CoolAce


Erichgue - Mo 01.09.08 16:29

user profile iconcoolace hat folgendes geschrieben:
Hy,

hab die geschichte mal aus einem frühreren Thread versucht anzupassen

...

aber irgendwo ist hier noch ein Gedankenfehler, er zeigt gar nichts an?

LG

CoolAce


Hallo CoolAce

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
DateTime date;
DateTime dateFound = DateTime.MaxValue;
int foundIndex = -1;
DateTime foundDate = DateTime.Now;

  for (int i = 0; i < listBox1.Items.Count; i++)
  {
    date = DateTime.Parse(listBox1.Items[i].ToString());
    // Jahr durch aktuelles Jahr ersetzen
    date = new DateTime(DateTime.Now.Year, date.Month, date.Day);
       
    if ((date >= DateTime.Now)  && (date < dateFound))
    {
       dateFound = date;
       foundIndex = i;
    }
  }


foundIndex wäre dann dein Object!
Ich habes mit einer Stringlist und deinen Datumswerten versucht. Klappt wunderbar!


coolace - Mo 01.09.08 16:56

hy

vielen Dank für deine Mühe, hab aber noch das problem das ich es nicht richtig umsetzen kann,
entweder nicht mein Tag heut oder ich seh den Wald vor lauter Bäumen nicht mehr.

Ich hab das komplette Projekt mal angehängt, könntest du mal drüberschauen was ich hier falsch mach?

Danke und Gruß

Coolace


Kha - Mo 01.09.08 17:41

Dein ursprünglicher Ansatz war doch fast richtig, du hättest nur noch das hier umsetzen müssen:
user profile iconKha hat folgendes geschrieben:
"Irgendwie" ist nie eine gute Fehlerbeschreibung.
Du kannst zwei DateTimes direkt miteinander vergleichen, die innere Schleife brauchst du also gar nicht. Außerdem macht es wohl keinen Sinn, nach einem Treffer die Suche fortzusetzen ;).


coolace - Mo 01.09.08 17:44

Das Problem ist das der erste Treffer ja nicht der richtige sein muss, da danach noch weitere richtige Treffer sein können wo das Datum des Monats kleiner ist als der des ersten Treffers


Kha - Mo 01.09.08 17:47

Tut mir leid, wenn sich etwas verändert hat, aber in deinem letzten Thread war deine Liste noch aufsteigend sortiert :nixweiss: .


coolace - Mo 01.09.08 17:53

Die Sortierung hat ja gepasst nach meinem letzten Thread, nur das Problem ist mit den Jahreszahlen

z.B. 12.10.1963 anna
08.01.1966 tanja
10.10.1990 lenz
11.10.1991 die
hier wäre der richtig vom heutigen Datum ausgehend der lenz da er vom Monat her größer als 9 ist und vom Tag
der kleinste in dem Monat

sorry für meine verwirrenden Formulierungen aber ich bastel schon seit Tagen dran rum


Kha - Mo 01.09.08 18:03

user profile iconKha hat folgendes geschrieben:
Du kannst zwei DateTimes direkt miteinander vergleichen, die innere Schleife brauchst du also gar nicht.
Ich weiß wirklich nicht, wie ich das noch umformulieren soll :nixweiss: , bei Erichgue hättest du es auch schon sehen sollen.

Na gut, ich versuch's: Tag und Monat brauchen dich doch überhaupt nicht zu interessieren, du willst einfach nur das erste Datum, das später als heute ist.


lothi - Mo 01.09.08 20:12

Hallo
Zitat:

a gut, ich versuch's: Tag und Monat brauchen dich doch überhaupt nicht zu interessieren, du willst einfach nur das erste Datum, das später als heute ist.

Ich glaube schon da ja drum geht welcher Geburtstag am nächsten am heutigen Datum liegt.

Liste mit Geburtsdatum ==> sortierte Liste mit Geburtsdatum von jetzt weg. In diesem Fall ist ja das Jahr nicht wichtig sondern nur der Tag und der Monat. Also die Differenze von Heute minus Geburtstag ohne Jahr. Das Datum mit dem kleinsten minus Wert ist am nächsten vom Geburtstag. 0 == Heute
Die mit plus sind schon zu alt.
Noch etwas die Sortierung des Alters und die Ausgabe des Geburtstags gehört nicht in den GUI, sondern sollte eine eigene Klasse bilden.


Christian S. - Mo 01.09.08 20:18

@coolace: Wieso hab ich mir hier die Mühe gemacht? [http://www.c-sharp-forum.de/viewtopic.php?t=85644&start=0&postorder=asc] :?


coolace - Mo 01.09.08 22:44

@ Christian S.

Sorry, hab es ja versucht umzusetzen, siehe posting oben aber das Problem ist das ich
es nicht hinbekam auf mein Projekt umzumünzen.


Jetzt hab ich es soweit hinbekommen, bekomm aber eine NullReferenceException, was hab ich falsch gemacht?

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
  for (int i = 0; i < liste.Count; i++)
              {
                 //Geburtstage im aktuellen Jahr 
                 DateTime compare = new DateTime(aktuell.Year,liste[i].Gebdatum.Month, liste[i].Gebdatum.Day);
             <span style="color: red">    if ((compare.CompareTo(aktuell) >= 0) && (aktuell - compare) < (aktuell - naechster.Gebdatum) /*näher </span>dran als der bisher "beste" */)
                     naechster = liste[i];
              }             
            
            txtage.Text = naechster.Alter();
            txtgeburtstag.Text = naechster.Gebname;
        }


Das ganze bei i = 2 aber der Datensatz ist exakt der selbe wie die anderen ?

Hoffe um Nachsicht und versuch mich zu bessern

Gruß

Coolace


Kha - Mo 01.09.08 23:04

Langsam krieg ich hier die Krise :nut: .

C#-Quelltext
1:
2:
3:
4:
5:
foreach (daten item in liste)
  if (item >= DateTime.Today) {
    // TextBoxen füllen...
    break;
  }

So. Wenn liste aufsteigend sortiert ist, muss das funktionieren. Keine Widerrede :P .

user profile iconcoolace hat folgendes geschrieben:
Jetzt hab ich es soweit hinbekommen, bekomm aber eine NullReferenceException, was hab ich falsch gemacht?
Dann hast du Christians Code wohl nur zur Hälfte übernommen, genauer gesagt nächster nicht initialisiert. Da die Liste damals aber noch nicht sortiert war, nimm jetzt lieber meinen Code :mrgreen: .
Allerdings sieht es nicht gerade so aus, als ob du Christians Schnipsel verstanden hättest. Vielleicht solltest du doch erst einmal Anfängerliteratur wie das Galileo OpenBook zur Hand nehmen :| .


coolace - Mo 01.09.08 23:09

Hy,

auch wenn meine Fragen verwirrt klingen aber ich denk schon das ich Sie verstanden habe,
So dies ist der Teil meines Projekts wo die Form1 geladen wird und die Funktion mit
der Auswahl aufgerufen wird

C#-Quelltext
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:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
InitializeComponent();
            try
            {
                lbldate.Text = DateTime.Now.ToLongDateString();
                //fügt die Aufgaben und Notizen hinzu
                rtfbox.LoadFile(@"E:\Butler\notizen.rtf");
                //fügt die Geburtstagsinfos ein
                
                using (FileStream fs = File.OpenRead(@"E:\Butler\geburtstag.xml"))
                liste = (List<daten>) xs.Deserialize(fs);
            Geburtstagskind();
            }
            catch (Exception)
            {
                MessageBox.Show(this"Eine der Dateien existiert nicht""Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
                if (File.Exists(@"E:\Butler\notizen.rtf"))
                {

                }
                else
                {
                    File.Create(@"E:\Butler\notizen.rtf");
                }

                if (File.Exists(@"E:\Butler\geburtstag.xml"))
                {
             
                }
                else
                {
                    File.Create(@"E:\Butler\geburtstag.xml");
                }
            }
           


public void Geburtstagskind()
        {
            daten naechster = null;
            DateTime aktuell = DateTime.Now;
            foreach (daten temps in liste)
            {
                lbox.Items.Add(temps.ToString());
            }

            if (liste.Coun >=1)
            naechster =  liste[0];
            for (int i = 0; i < liste.Count; i++)
            {
                //Geburtstage im aktuellen Jahr 
                DateTime compare = new DateTime(aktuell.Year, liste[i].Gebdatum.Month, liste[i].Gebdatum.Day);
                if ((compare.CompareTo(aktuell) >= 0) && (aktuell - compare) < (aktuell - naechster.Gebdatum) /*näher dran als der bisher "beste" */)
                    naechster = liste[i];
            }

            txtage.Text = naechster.Alter();
            txtgeburtstag.Text = naechster.Gebname;
            
        }


Ich hab Sie soweit hinbekommen das Sie ohne Maulen läuft aber er gibt den falschen aus, Tagetechnisch gäbe es bei
mir noch bessere Kandidaten
Sorry

Gruß

Coolace


Christian S. - Mo 01.09.08 23:15

user profile iconKha hat folgendes geschrieben:
Da die Liste damals aber noch nicht sortiert war, nimm jetzt lieber meinen Code :mrgreen: .

Bringt die Sortierung denn wirklich was, wenn man das nächste Geburtstagskind haben will? In der Sortierung steht der 3.9.1960 vor dem 2.9.1990, aber trotzdem ist letzterer das nächste Geburtstagskind.


coolace - Mo 01.09.08 23:20

Hy,

hab im Anhang einen Screenshot mit den Geburtstagskindern (alles fiktive zwecks Datenschutz)
und da ist der letzt jörg der der genommen wird obwohl der 1 vor jörg der richtige wäre


lothi - Di 02.09.08 08:19

Hallo

So jetzt will ich auch noch mal den Senf dazugeben.

Es ist ja egal ist ob das Geburttagsking 1933 oder 1944 oder 2007 geboren ist, hat es trotzdem heute geburttag. Also ist die Jahrzahl nicht nötig. Da du aber nicht nur Monat und Tag sortieren kannst würde ich jetzt eine neue Liste machen und du gibst jeden Datum die gleich Jahrzahl dann
Heute minus neues Datum = ein TimSpan mit Tagen. Alle Werte die >0 haben den Geburtag schon vorbei == 0 haben heute Geburtstag <0 haben in sovielen Tagen Geburtstag.
Du musst nur gucken das du dann der richtige Name zum richtigen Datum hast. Mit einer SortedList oder SortedDictionary.

Gruss Lothi


Erichgue - Di 02.09.08 09:26

user profile iconcoolace hat folgendes geschrieben:
hy

vielen Dank für deine Mühe, hab aber noch das problem das ich es nicht richtig umsetzen kann,
entweder nicht mein Tag heut oder ich seh den Wald vor lauter Bäumen nicht mehr.

Ich hab das komplette Projekt mal angehängt, könntest du mal drüberschauen was ich hier falsch mach?

Danke und Gruß

Coolace


Hallo CoolAce
Gerne!


C#-Quelltext
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:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
//Auswahl der richtigen Person und anzeige in der Listbox
        public void Geburtstagskind()
        {
      // Neu Erichgue
      txtage.Text = "";
      txtgeburtstag.Text = "";
      // #Neu Erichgue

            //DateTime aktuell = DateTime.Now;
            foreach (daten temps in liste)
            {
        lbox.Items.Add(temps.ToString());
            }

            DateTime date;
            DateTime dateFound = DateTime.MaxValue;
            int foundIndex = -1;
            DateTime foundDate = DateTime.Now;

            for (int i = 0; i < lbox.Items.Count; i++)
            {
                date = DateTime.Parse(lbox.Items[i].ToString());
                // Jahr durch aktuelles Jahr ersetzen
                date = new DateTime(DateTime.Now.Year, date.Month, date.Day);

                if ((date >= DateTime.Now) && (date < dateFound))
                {
                    dateFound = date;
                    foundIndex = i;

          // Deaktiviert Erichgue
                    // txtage.Text = liste[i].Alter();
                    // txtgeburtstag.Text = liste[i].Gebname;
          // #Deaktiviert Erichgue
                }
            }

      // Neu Erichgue
      if (foundIndex > -1)
      {
        txtage.Text = liste[foundIndex].Alter();
        txtgeburtstag.Text = liste[foundIndex].Gebname;
      }
      // #Neu Erichgue


Hups! Zu schnell geschossen! So geht es nicht! Warte mal, der richtige Code kommt gleich!


Erichgue - Di 02.09.08 09:38

user profile iconcoolace hat folgendes geschrieben:
hy

vielen Dank für deine Mühe, hab aber noch das problem das ich es nicht richtig umsetzen kann,
entweder nicht mein Tag heut oder ich seh den Wald vor lauter Bäumen nicht mehr.

Ich hab das komplette Projekt mal angehängt, könntest du mal drüberschauen was ich hier falsch mach?

Danke und Gruß

Coolace


So, jetzt müßte es passen.


C#-Quelltext
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:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
//Auswahl der richtigen Person und anzeige in der Listbox
public void Geburtstagskind()
{
  DateTime date;
  DateTime dateFound = DateTime.MaxValue;
  DateTime foundDate = DateTime.Now;
  daten gebFound = null;

  txtage.Text = "";
  txtgeburtstag.Text = "";

  lbox.Items.Clear();
  lbox.BeginUpdate();

        //DateTime aktuell = DateTime.Now;
        foreach (daten temps in liste)
        {
    // Listbox füllen
    lbox.Items.Add(temps.ToString());

    // nächstes Geburtstagskind suchen
    date = temps.Gebdatum;
    // Jahr durch aktuelles Jahr ersetzen
    date = new DateTime(DateTime.Now.Year, date.Month, date.Day);

    if ((date >= DateTime.Now) && (date < dateFound))
    {
      dateFound = date;
      gebFound = temps;
    }
         }

   lbox.EndUpdate();

   if (gebFound != null)
  {
    txtage.Text = gebFound.Alter();
    txtgeburtstag.Text = gebFound.Gebname;
  }

 }


Wärend du die Liste füllst, kannst du gleich das Geb-Kind ermitteln.
So hast du auch am Schluß das Objekt deines Geb-Kindes und kannst damit weiter arbeiten.

Erich


coolace - Di 02.09.08 14:52

Hy,

vielen vielen Dank an alle die mir hierbei geholfen haben (50 Kästen Bier in die runde stell).

Gruß

Coolace