Avatar billede netspinner Nybegynder
18. maj 2006 - 18:45 Der er 38 kommentarer og
2 løsninger

Datoalgoritme til to ting - hurtig hjælp behøves

Hej,
Dette er virkelig vigtigt for mig, at det bliver løst så hurtigt som muligt, så jeg håber virkelig på en masse hjælp fra jer derude...!


Jeg skal kode en save- og søge-funktion, hvor jeg behøver hjælp til følgende:

1) Jeg skal først validere om input i et JTextField er i korrekt datoformat, nemlig dd-mm-yy (f.eks. 18-05-06). Hvis det er korrekt, gemmes dato sammen med nogle andre poster i en fil. Hvis ikke, skal en messageDialog give besked om at man skal forsøge igen.

2) Derefter skal det være muligt at søge på datoformat fra samme JTextField. Dvs. at man skal kunne søge på en vilkårlig dato, f.eks. 18-05-06, hvorefter man klikker på en knap "Søg dato" og alle poster gemt med den givne dat vises i et felt. Hvis forkert, skal en messageDialog give besked om at formatet er forkert - f.eks. hvis man kommer til at taste 18-13-06 eller 32-12-06 (fordi der ikke eksisterer en 13. måned eller en 32. dag).

3) Til slut vil jeg gerne gøre det muligt at søge på måned på to måder: A) Hvor man kan indtaste en af de tolv måneder [01-12], dvs. midten af dato-formatet, hvorefter man klikker på en knap "Søg måned" og alle poster i den givne måned vises, og B) Hvor man kan indtaste månedens navn som en streng ["januar"-"december"] og klikke på selv samme knap, "Søg måned".
Avatar billede arne_v Ekspert
18. maj 2006 - 19:56 #1
re 1)

SimpleDateFormat parse og catch exception
Avatar billede netspinner Nybegynder
18. maj 2006 - 20:11 #2
Min kode for at kunne tilføje et arrangement, hvor datovalideringen også skal foregå, ser indtil videre sådan ud...


      if(e.getSource() == addEvent || e.getSource() == addBtn)
      {
          String eventname = eventnameField.getText();
          String title = titleField.getText();
          String artist = artistField.getText();
          String date = dateField.getText();
          String genre = genreField.getText();
          String time = timeField.getText();
          String location = locationField.getText();
          String price = priceField.getText();
         
          Book book = new Book(eventname, title, artist, date, genre, time, location, price);
       
          if (eventname.length()==0 || title.length()==0 || artist.length()==0 || genre.length()==0 ||
              date.length()==0 || time.length()==0 || location.length()==0 || price.length()==0)
          {
            infoLabel.setText("Tjek om alle felter er udfyldt og at datoen er i DD-MM-ÅÅ format!");
          }
          else
          {
            try
            {
              archive.addBook(book);
              displayArea.setText("Arrangement tilføjet med succes!");
              clearFields();
              infoLabel.setText(" ");
            }
            catch (InvalidISBNException ex)
            {
              infoLabel.setText(ex.getMessage());
              displayArea.setText(" ");
            }
          }
        }
Avatar billede netspinner Nybegynder
18. maj 2006 - 21:09 #3
Hjælp mig lige ud engang, please :)
Avatar billede arne_v Ekspert
18. maj 2006 - 21:52 #4
private static DateFormat df = new SimpleDateFormat("dd-MM-yy");

og

      try {
        df.parse(datefield);
        // ok
      } catch (ParseException e) {
        // error
      }
Avatar billede netspinner Nybegynder
19. maj 2006 - 09:29 #5
Hmm, jeg tilføjer private static DateFormat df = new SimpleDateFormat("dd-MM-yy"); sammen med mine andre variabeldeklarationer.

Når jeg så tilføjer df.parse(dateField); i try-catch blokken i addEvent/addBtn metoden jeg har listet her, laver den vrøvl om at parse ikke er en metode for et JTextField.
Avatar billede arne_v Ekspert
19. maj 2006 - 13:28 #6
df.parse(datefield.getText());
Avatar billede mikkelbm Nybegynder
20. maj 2006 - 12:00 #7
1) Har Arne svaret på. Den kan udvides til at laves som en metode:

public boolean validateDate(String date)
{
  DateFormat df = new SimpleDateFormat("dd-MM-yy");
  try
  {
      df.parse(datefield);
      return true;
  }
  catch (ParseException e)
  {
      return false;
  }
}

Og du kalder den så bare sådan her:

if (!validateDate (datefield.getText())
{
  JOptionPane.showMessage ("Fejl i dato");
  return;
}


2)

Kunne være noget a la:

public Book[] findBooksFromDate (String date)
{
  if (!validateDate (datefield.getText())
  {
      JOptionPane.showMessage ("Fejl i dato");
      return new Book[0];
  }
 
  Book[] books = archive.getBooks(); // Du må have en eller anden metode hvor du kan hente alle Book's ud?
  ArrayList foundBooks = new ArrayList();
 
  for (int i = 0; i < books.length; i++)
  {
      if (books[i].getDate().equals (date))
        foundBooks.add (books[i]);
  }
 
  return (Book[])foundBooks.toArray (new Book[0]);
}

3)

Måske:

3a)

public Book[] findBooksFromMonth (int month) throws ParseException
{
  if (month < 0 || month > 12)
  {
      JOptionPane.showMessage ("Fejl i måned");
      return new Book[0];
  }
 
  Book[] books = archive.getBooks();
  ArrayList foundBooks = new ArrayList();
 
  for (int i = 0; i < books.length; i++)
  {
      String month = books.getDate().split("-")[1];
      int intMonth = Integer.parseInt (month);
      if (intMonth == month)
        foundBooks.add (books[i]);
  }
}

3b)

public int convertMonth (String month)
{
  if (month.equalsIgnoreCase("januar"))
      return 0;
  if (month.equalsIgnoreCase("februar"))
      return 1;
  if (month.equalsIgnoreCase("marts"))
      return 2;
  if (month.equalsIgnoreCase("april"))
      return 3;
  if (month.equalsIgnoreCase("maj"))
      return 4;
  if (month.equalsIgnoreCase("juni"))
      return 5;
  if (month.equalsIgnoreCase("juli"))
      return 6;
  if (month.equalsIgnoreCase("august"))
      return 7;
  if (month.equalsIgnoreCase("setptember"))
      return 8;     
  if (month.equalsIgnoreCase("oktober"))
      return 9;     
  if (month.equalsIgnoreCase("november"))
      return 10;   
  if (month.equalsIgnoreCase("december"))
      return 11;     
}

Og den bruges så på følgende måde:

int month = convertMonth ("februar");
Book[] books = findBooksFromMonth(month);



Det er måske ikke den bedste søgealgoritme der findes, da den løber alle poster igennem lineært. Men det er svært at gøre den bedre uden at vide om du har database til rådighed og om du har et persistenslag hvor du cacher dine objekter og lignende ting.
Avatar billede mikkelbm Nybegynder
20. maj 2006 - 12:02 #8
Og til 3b mangler der lige en default returværdi:

public int convertMonth (String month)
{
  if (month.equalsIgnoreCase("januar"))
      return 0;
  if (month.equalsIgnoreCase("februar"))
      return 1;
  if (month.equalsIgnoreCase("marts"))
      return 2;
  if (month.equalsIgnoreCase("april"))
      return 3;
  if (month.equalsIgnoreCase("maj"))
      return 4;
  if (month.equalsIgnoreCase("juni"))
      return 5;
  if (month.equalsIgnoreCase("juli"))
      return 6;
  if (month.equalsIgnoreCase("august"))
      return 7;
  if (month.equalsIgnoreCase("setptember"))
      return 8;   
  if (month.equalsIgnoreCase("oktober"))
      return 9;   
  if (month.equalsIgnoreCase("november"))
      return 10; 
  if (month.equalsIgnoreCase("december"))
      return 11; 

  return -1; 
}

Hvis metoden returnerer -1, så ved du at der ikke er indtastet en gyldig måned.
Avatar billede netspinner Nybegynder
20. maj 2006 - 12:13 #9
Okay, jeg prøver at implementere det i løbet af dagen. Mange tak for dit input!
Avatar billede netspinner Nybegynder
20. maj 2006 - 14:18 #10
mikkelbm > Jeg har lagt hele mit projekt i en fil, som du kan hente her: http://peecee.dk/?id=40049

Der får du ALT med.

Hvis du vil forsøge at få det til at virke, får du en masse ros & points! :-)
Avatar billede netspinner Nybegynder
20. maj 2006 - 14:31 #11
Jeg har fundet lidt ud af, at det nok er bedst hvis alle months bliver hentet ind i f.eks. en JComboBox ved opstart, og når brugeren vælger en måned fra listen, f.eks. maj, bliver alle arr. fra den måned vist. Endvidere har jeg tænkt lidt på, om man ved visning af hele listen (listeventsBtn), kan sortere arr. efter dato?
Avatar billede mikkelbm Nybegynder
21. maj 2006 - 10:29 #12
Jeg har desværre ikke tid til at kigge på det idag .
Måske imorgen aften - men jeg kan ikke garantere det.
Avatar billede netspinner Nybegynder
21. maj 2006 - 12:32 #13
Helt i orden :)
Avatar billede netspinner Nybegynder
22. maj 2006 - 18:55 #14
Hej mikkelbm, jeg har løst alt pånær det med at sortere arrangementer efter dato, så hvis du bare kigger på det, er det fint :-)
Avatar billede mikkelbm Nybegynder
22. maj 2006 - 18:59 #15
Jeg skulle faktisk lige til at kigge på det :) Kan du fortælle mig hvor det er du vil have dine data sorteret? Altså hvilken fil og ca. linjenummer.
Avatar billede netspinner Nybegynder
22. maj 2006 - 19:04 #16
Hmm, ja, det er egentlig lidt svært at svare på. Det er jo sådan, at EventIO.java håndterer læsning og skrivning til harddisken (du kan selv lige se dens opbygning). Men i GUI.java, hvor jeg har min actionPerformed metode, har jeg alle søgealgoritmer. Så måske det skal være under if(e.getSource() == listevents)... ?
Det hjælper nok en del hvis du bygger projektet.
Avatar billede mikkelbm Nybegynder
22. maj 2006 - 19:27 #17
Jeg kigger lige lidt på det.
Avatar billede mikkelbm Nybegynder
22. maj 2006 - 19:36 #18
1) Tilføj følgende statiske metode i "EventComponents.java" :

public static java.util.Comparator DateComparable()
{
    final java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd-MM-yy");
    java.util.Comparator com = new java.util.Comparator()
      {
          public int compare(Object o1, Object o2)
          {
              EventComponents ev1 = (EventComponents)o1;
              EventComponents ev2 = (EventComponents)o2;
             
              try
              {             
                  java.util.Date date1 = sdf.parse(ev1.getDate());
                  java.util.Date date2 = sdf.parse(ev2.getDate());
                 
                  return date1.compareTo(date2);
              }
              catch (Exception e){e.printStackTrace();}
             
              return 0;
          }
      };
      return com;
}

Tilføj følgende metode til "BookTable.java":

public EventComponents[] getAllBooks()
{
    return (EventComponents[])events.values().toArray(new EventComponents[0]);
}

Og i din "GUI.java" ændrer du din if til:

if(e.getSource() == listevents || e.getSource() == listeventsBtn)
{
    String details = "ARKIVEREDE ARRANGEMENTER\n";
    String separateEvents = "----------------------------------------------------------";

    EventComponents[] books = archive.getAllBooks();
    Arrays.sort(books, EventComponents.DateComparable());
           
    for (int i = 0; i < books.length; i++)
    {
        EventComponents nextBook = books[i];
                       
        details = details +"\n PROJEKTNAVN: " + nextBook.getEventName();
        details = details +"\n TITEL: " + nextBook.getTitle();
        details = details +"\n KUNSTNER(E): " + nextBook.getArtist();
        details = details + "\n GENRE: " + nextBook.getGenre();
        details = details + "\n MÅNED: " + nextBook.getMonth();
        details = details + "\n DATO: " + nextBook.getDate();
        details = details + "\n TIDSPUNKT: " + nextBook.getTime();
        details = details + "\n STED: " + nextBook.getLocation();
        details = details + "\n PRIS: " + nextBook.getPrice() + " kr.";
        details = details + "\n\n" + separateEvents + "\n";
    }
    displayArea.setText(details);
    infoLabel.setText(" ");
}

Så burde de blive sortet i kronologisk rækkefølge...
Avatar billede mikkelbm Nybegynder
22. maj 2006 - 19:39 #19
Og hvis du vil have at den også inkluderer tidspunkt i sorteringen:

public static java.util.Comparator DateComparable()
{
    final java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd-MM-yy HH:mm");
    java.util.Comparator com = new java.util.Comparator()
    {
        public int compare(Object o1, Object o2)
        {
            EventComponents ev1 = (EventComponents)o1;
            EventComponents ev2 = (EventComponents)o2;
           
            try
            {             
                java.util.Date date1 = sdf.parse(ev1.getDate() + " " + ev1.getTime());
                java.util.Date date2 = sdf.parse(ev2.getDate() + " " + ev2.getTime());
               
                return date1.compareTo(date2);
            }
            catch (Exception e){e.printStackTrace();}
           
            return 0;
        }
    };
    return com;
}
Avatar billede netspinner Nybegynder
22. maj 2006 - 19:45 #20
Tusind tak, jeg prøver lige at ændre filerne lidt senere!
Avatar billede netspinner Nybegynder
23. maj 2006 - 09:43 #21
Nu fik jeg tid til det. Det virker rigtig godt, så tak skal du ha' :-) Smid et svar...
Avatar billede netspinner Nybegynder
23. maj 2006 - 09:44 #22
arne_v, du må også gerne smide et svar :-)
Avatar billede mikkelbm Nybegynder
23. maj 2006 - 09:56 #23
Kommer her...
Avatar billede arne_v Ekspert
23. maj 2006 - 13:20 #24
jeg formoder at mikkel får 90% af points ...
Avatar billede netspinner Nybegynder
23. maj 2006 - 13:53 #25
Håber ikke nogen er stødt over pointfordelingen? :-S

Nuvel, jeg har en sidste ting til dig mikkelbm. Mit program er sådan set færdigt, men jeg fundet ud af at når man tilføjer et arrangement, må der gerne være en try-catch der sammenligner om datoformat stemmer overens med den måned brugeren har valgt - dvs. den skal brokke sig hvis man f.eks. vælger januar måned og i datofeltet angiver 05-05-06. Jeg har i øvrigt programmeret en JComboBox, der lister et arrays indhold (dvs. alle måneder), så brugeren ikke længere kan skrive måneden...

Any idea?
Avatar billede mikkelbm Nybegynder
23. maj 2006 - 13:57 #26
Jeg har en idé, men den kræver en lille smule omstrukturering.
Hvorfor er det egentlig at du gemmer måned og dato? Du har jo måned implicit i din dato?

Så min idé går ud på at skrotte måned og bare have en dato.
Avatar billede netspinner Nybegynder
23. maj 2006 - 13:58 #27
Ja, jeg ved det godt. Men min underviser mener at det vil være bedste løsning - give den mest optimale brugervenlighed for dummies...
Avatar billede mikkelbm Nybegynder
23. maj 2006 - 14:05 #28
Hmm... Tjah... Det er så ikke min mening, når du alligevel skal vælge dag og år - men den er vel heller ikke interessant, når din lærer mener noget andet :)

Du kan lave noget a la:

String date = "05-05-06";
String month = "6";

boolean monthOk = checkMonthAndDate (date, month);

//....

private boolean checkMonthAndDate (String date, int month)
{
  String dateSplit = date.split ("-");
  int monthInDate = Integer.parseInt (dateSplit[1]);

  return monthInDate == month;
}
Avatar billede mikkelbm Nybegynder
23. maj 2006 - 14:08 #29
Du kan også konvertere din date-string til den rigtig dato og hive måned ud af den.

private boolean checkMonthAndDate (String date, int month) throws Exception
{
  SimpleDateFormat sdf = new SimpleDateFormat ("dd-MM-yy");
  Date realDate = sdf.parse (date);
  GregorianCalendar cal = new GregorianCalendar();
  cal.setTime (realDate);
  int monthInDate = cal.get (Calendar.MONTH);

  return monthInDate == month;
}
Avatar billede netspinner Nybegynder
23. maj 2006 - 14:12 #30
Jo jo, jeg deler samme mening, og jeg behøver heller ikke at strukturere programmets logik sådan, men jeg orker næsten ikke at sidde og rode med det mere (læs: vil være færdig i løbet af i dag :)...
jeg skal i øvrigt også lige se om ikke jeg kan gøre det sådan, at priceField kun accepterer tal (doubles). Men så skal det vel gemmes anderledes i filen?
Avatar billede mikkelbm Nybegynder
23. maj 2006 - 14:18 #31
Nej, ikke nødvendigvis... Du kan jo bare lave en:

String price = "13.25";
boolean isNumber = checkIsNumber (price);

private boolean checkIsNumber (String number)
{
  try
  {
      Double.parse (number);
      return true;
  }
  catch (NumberFormatException e)
  {
      return false;
  }
}
Avatar billede netspinner Nybegynder
23. maj 2006 - 14:18 #32
Jeg kan ikke lige få din sidste metode til at virke - kan du ikke vise ud fra addEvent, hvordan den skal tilføjes..
Avatar billede mikkelbm Nybegynder
23. maj 2006 - 14:21 #33
Jeg har ikke lige noget Java installeret på den her maskine, så jeg kan ikke køre din kode.

Hvad får du af fejl?
Avatar billede netspinner Nybegynder
23. maj 2006 - 14:28 #34
Egentlig ikke en fejl. Du har oprettet en metode (checkMonthAndDate). Men i addEvent skal jeg vel referere til metoden, så den virker - eller helt undlade at skrive den som metode? Har lige testet med at oprette noget i januar og angivet september i datoformatet... der brokker den sig ikke, men tilføjer det :(

Min addEvent ser således ud:


      if(e.getSource() == addEvent || e.getSource() == addBtn)
      {
          String eventname = eventnameField.getText();
          String title = titleField.getText();
          String artist = artistField.getText();
          String genre = genreField.getText();
          String month = monthsCombo.getSelectedItem().toString();
          String date = dateField.getText();
          String time = timesCombo.getSelectedItem().toString();
          String location = locationField.getText();
          String price = priceField.getText();

          EventComponents evcomp = new EventComponents(eventname, title, artist, genre, month, date, time, location, price);
         
          if (eventname.length()==0 || !eventname.equalsIgnoreCase(eventnameField.getText()) || title.length()==0 || artist.length()==0 ||
              genre.length()==0 || date.length()==0 || time.length()==0 || location.length()==0 || price.length()==0)
          {
              infoLabel.setText("Tjek om alle felter er udfyldt!");
              Toolkit.getDefaultToolkit().beep();
          }
          else
          {
              try {
                  // Be stringent with the date format!
                  df.setLenient(false);
                  // Parse the date text and validate it
                  df.parse(dateField.getText());
                  archive.addEvent(evcomp);
                  displayArea.setText("Arrangement tilføjet med succes!");
                  clearFields();
                  infoLabel.setText(" ");
              }
              catch (InvalidENException ex)
              {
                  infoLabel.setText(ex.getMessage());
                  displayArea.setText(" ");
                  // Utilize Windows' standard Beep-sound
                  Toolkit.getDefaultToolkit().beep();
              }
              catch (ParseException parsing)
              {
                  JOptionPane.showMessageDialog(null, "Fejl i dato");
              }
            }
        }
Avatar billede mikkelbm Nybegynder
23. maj 2006 - 14:35 #35
Sådan her måske:

else if (!checkIsNumber (month))
{
  infoLabel.setText("Måned ikke korrekt!");
  Toolkit.getDefaultToolkit().beep();
}
else if (!checkMonthAndDate (date, month))
{
  infoLabel.setText("Dato og måned stemmer ikke overens!");
  Toolkit.getDefaultToolkit().beep();
}
Avatar billede netspinner Nybegynder
23. maj 2006 - 14:44 #36
Når jeg har tilføjet de to else if-betingelser til min addEvent, får jeg flg. fejl: checkMonthAndDate(java.lang.String,int) in GUI cannot be applied to (java.lang.String,java.lang.String) - hvad mangler jeg lige her? :)
Avatar billede mikkelbm Nybegynder
23. maj 2006 - 14:47 #37
At parse din month til en integer. Det kan du enten gøre inden du smider den ned i metoden, eller du kan ændre metoden til at tage imod en String i stedet for, og så parse den String nede i metoden.
Avatar billede netspinner Nybegynder
23. maj 2006 - 15:02 #38
Hmm det er godt nok lidt svært at overskue lige nu. Det ville selvfølgelig hjælpe hvis du havde adgang til min kode & java :)
Avatar billede mikkelbm Nybegynder
23. maj 2006 - 15:11 #39
Jeg tror altså du gør det meget mere svært end det i virkeligheden er.

Prøv at ændre metoden til:

private boolean checkMonthAndDate (String date, String month)
{
  int monthInt = Integer.parseInt (month);
  String dateSplit = date.split ("-");
  int monthInDate = Integer.parseInt (dateSplit[1]);

  return monthInDate == monthInt;
}
Avatar billede netspinner Nybegynder
23. maj 2006 - 15:21 #40
Det er stadig helt skørt... jeg lader det lige være indtil du får tid til at lege med min kode og selv ser om du kan få det til at virke. Indtil da lader jeg det altså bare være...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester