Avatar billede r9 Nybegynder
27. maj 2002 - 10:40 Der er 12 kommentarer og
1 løsning

Dato

Hejsa

Jeg skal bruge en metode som validerer en datostring.

Følgende formater er gyldige:
dd-mm-yyyy
dd/mm/yyyy
dd.mm.yyyy

d-m-yyyy
dd-m-yyyy
d-mm-yyyy

d-m-yy
dd-m-yy
d-mm-yy

d/m/yyyy
dd/m/yyyy
d/mm/yyyy

d/m/yy
dd/m/yy
d/mm/yy

d.m.yyyy
dd.m.yyyy
d.mm.yyyy

d.m.yy
dd.m.yy
d.mm.yy


Alt andet er IKKE gyldigt!
Avatar billede codemon Nybegynder
27. maj 2002 - 11:21 #1
Brug SimpleDateFormat, der kan du give et mønster med applyPattern metoden og så prøve at parse din streng til et Date objekt med parse(String ). Hvis der ikke kastes en exception er mønsteret ok.

public boolean validate(string dato)
{
    SimpleDateFormat mySimpleDateFormat = new SimpleDateFormat();
  String validatePattern[] =
      {"dd-MM-yyyy",
      "dd/MM-yyyy",
      "dd.MM.yyyy",
      ... // osv.
  try
  {
      boolean ok = false;
      for (int i=0; i<validatePattern.length; i++)
      {
          mySimpleDateFormat.applyPattern(validatePattern[i]);
          mySimpleDateFormat.parse(dato); // parseexception hvis formatet ikke passer.
          ok=true;
          ... // osv
Avatar billede disky Nybegynder
27. maj 2002 - 11:22 #2
Jeg må give codemon helt ret, det er nok den nemmeste metode at gøre det på.

Eller du kan parse datoen, f.eks. ved først at tilpasse den til et bestemt format for derefter at konvertere den.

At bruge en exception specifik metode er lidt tung i performance.
Avatar billede jakoba Nybegynder
27. maj 2002 - 11:57 #3
på den hårde måde:

private int laesTal ( String str, int fra, int til ) {
    int tal = 0;
    try {
        tal = Integer.parseInt( str );
    } catch NumberFormatException(e) {
        return -1;  // failed: ugyldig talværdi
    }
    if ( tal < fra || tal > til ) {
        return -1;  // failed: ugyldigt tal.
    }
    return tal;
} //end laesTal( String, int, int ) -> tal OR -1

public Calendar checkDatoStreng( String dinStreng ) {
    static String skilleTegnListe = "/-.";
    char skilleTegn = ' ';
    for (int i=0; i<skilleTegnListe.length(); i++ ) {
        if ( dinStreng.indexOf( skilleTegnListe.charAt(i).valueOf() >= 0 ) {
            skilleTegn = skilleTegnListe.charAt(i);
        }
    }
    if ( skilleTegn == ' ' ) {
        return null;  // failed: Det er ikke anvendt et af de gyldige skilletegn
    }
    int idxBeg = 0;
    int idxEnd = dinStreng.indexOf( skilleTegn );
    if ( idxEnd < 1 || idxEnd > 2 ) {
        return null;  // failed: for få eller for mange cifre i datoen
    }
    int dato = laesTal ( dinstreng.substring(0,idxEnd), 1, 31 );
    if ( aar < 0 ) {
        return null;  // failed: ugyldigt dato.
    }
    idxBeg = idxEnd+1;
    int idxEnd = dinStreng.indexOf( skilleTegn, idxBeg );
    if ( idxEnd < idxBeg+1 || idxEnd > idxbeg+2 ) {
        return null;  // failed: for få eller for mange cifre i maaneden
    }
    int maaned = laesTal ( dinstreng.substring(idxBeg,idxEnd), 1, 12 );
    if ( aar < 0 ) {
        return null;  // failed: ugyldigt måned.
    }
    idxBeg = idxEnd+1; // nu skal resten være årstal.
    int idxEnd = dinStreng.length();
    if ( idxEnd != idxBeg+2 || idxEnd != idxbeg+4 ) {
        return null;  // failed: forkert antal cifre i årstallet
    }
    int aar = laesTal ( dinstreng.substring(idxBeg,idxEnd), 0, 9999 );
    if ( aar < 0 ) {
        return null;  // failed: ugyldigt årstal.
    }
    if ( aar < 100 ) {
        // konverter til 4cifret årstalværdi efter den regel du nu har valgt at bruge
    }
    Calendar resultat = new Calendar();
    resultat.setLenient( true ); // en 'gal' dato som 30-februar bliver lavet som 2-marts
    resultat.set( aar, maaned, dag ); //NB måske time.minut,sekund,... skal nulstilles.
                  // NB: en 'gal' dato som 30-februar bliver lavet som 2-marts
    return resultat;
} //end checkDatoStreng( String ) -> Calendar OR null

mvh JakobA
Avatar billede jakoba Nybegynder
27. maj 2002 - 12:03 #4
Boo hiss. logisk fejl:{ det skal være AND i linien:
    if ( idxEnd != idxBeg+2 && idxEnd != idxbeg+4 ) {
Avatar billede r9 Nybegynder
27. maj 2002 - 12:14 #5
codemon:

hvis jeg kalder metoden med:
boolean b =d.validate("10.10.2000") ;
får jeg true.


Men hvis jeg har flere strings i mit array, så går det galt!

f.eks.
String validatePattern[] = {"dd.MM.yyyy", "dd-MM-yyyy"};
giver en: java.text.ParseException: Unparseable date: "10.10.2000"

Hvad er fejlen?


public boolean validate(String dato)
{
    SimpleDateFormat mySimpleDateFormat = new SimpleDateFormat();
    String validatePattern[] = {"dd.MM.yyyy"};

    boolean ok = false;

  try
  {

      for (int i=0; i<validatePattern.length; i++)
      {
          mySimpleDateFormat.applyPattern(validatePattern[i]);
          mySimpleDateFormat.parse(dato);
          ok=true;
      }
  }

    catch(ParseException pe) {
      pe.printStackTrace();
      ok=false;
  }


    return ok;


}
Avatar billede codemon Nybegynder
27. maj 2002 - 12:41 #6
At der kommer en ParseException betyder ikke at formatet er ugyldigt. Der er jo flere og kun én passer. Formatet er ugyldigt hvis der kommer parse exception på ALLE.

Jeg kan nu se at for løkken skal være udenom try-catch sætningen. Det andet vil ikke virke. Din boolean ok skal så kun sættes til true når der ikke er exception. (en break eller boolsk test i while løkke i stedet for, for-løkke kunne evt. stoppe løkken når et valid mønster er fundet)
Avatar billede codemon Nybegynder
27. maj 2002 - 12:44 #7
boolean ok = false;
    for (int i=0; i<validatePattern.length; i++)
    {
        try
        {
            mySimpleDateFormat.applyPattern(validatePattern[i]);
            mySimpleDateFormat.parse(dato); // parseexception hvis formatet ikke passer.
            ok=true; // når kun her hvis pattern er gyldigt
        }
        catch (ParseException e)
        {
            // do-nothing - prøv næste pattern
        }
    }

evt. while (i<validatePattern.length && !ok) // stop løkken hvis gyldigt mønster bliver fundet.
Avatar billede r9 Nybegynder
27. maj 2002 - 19:26 #8
jakoba:

smid et svar, så er der nogle point på vej
Avatar billede r9 Nybegynder
27. maj 2002 - 19:28 #9
sorry jakoba.

Det var meningen at dig og Codemon skulle have haft 25 point hver.
Er det noget du kan klare Codemon?
Avatar billede jakoba Nybegynder
27. maj 2002 - 19:30 #10
helt ok. Jeg har fundet ca 12 grove fejl i mit "bidrag" siden jeg postede :(
så det er ikke points værd.

mvh JakobA
Avatar billede codemon Nybegynder
27. maj 2002 - 22:36 #11
Jamen det kan jeg da, jakobA der er point til dig hvis det skal være.
Avatar billede codemon Nybegynder
27. maj 2002 - 23:00 #12
r9 er du hardcore så snub parse logikken fra kildekoden af SimpleDateFormat.parse(String, ParsePosition), så kan du selv implementere en validDate som ikke bruger exception (eller fortsæt jakobas arbejde) og så kom jeg til at lukke Date klassen op og kigge på dens parse metode, aldrig har jeg set noget lignende, den er godt nok grum.
Avatar billede jakoba Nybegynder
27. maj 2002 - 23:12 #13
Hvis du ikke har det til at virke endnu er her den testklasse jeg endte med. Den ser ud til at være ok :-)

import java.util.*;

class TestDatocheck {

  private int laesTal ( String str, int fra, int til ) {
      int tal = 0;
      try {
          tal = Integer.parseInt( str );
      } catch (NumberFormatException e) {
          return -1;  // failed: ugyldig talformat
      }
      if ( tal < fra || tal > til ) {
          return -1;  // failed: ugyldigt tal.
      }
      return tal;
  }

String skilleTegnListe = "/-.";

public Calendar checkDatoStreng( String dinStreng ) {
    char skilleTegn = ' ';
    for (int i=0; i<skilleTegnListe.length(); i++ ) {
        if ( dinStreng.indexOf( (int)skilleTegnListe.charAt(i) ) >= 0 ) {
            skilleTegn = skilleTegnListe.charAt(i);
        }
    }
    if ( skilleTegn == ' ' ) {
        return null;  // failed: Det er ikke anvendt et af de gyldige skilletegn
    }
    int idxBeg = 0;
    int idxEnd = dinStreng.indexOf( skilleTegn );
    if ( idxEnd < 1 || idxEnd > 2 ) {
        return null;  // failed: for få eller for mange cifre i datoen
    }
    int dato = laesTal ( dinStreng.substring(0,idxEnd), 1, 31 );
    if ( dato < 0 ) {
        return null;  // failed: ugyldigt dato.
    }
    idxBeg = idxEnd+1;
    idxEnd = dinStreng.indexOf( skilleTegn, idxBeg );
    if ( (idxEnd < idxBeg+1) || (idxEnd > idxBeg+2) ) {
        return null;  // failed: for få eller for mange cifre i maaneden
    }
    int maaned = laesTal ( dinStreng.substring(idxBeg,idxEnd), 1, 12 );
    if ( maaned < 0 ) {
        return null;  // failed: ugyldigt måned.
    }
    idxBeg = idxEnd+1; // nu skal resten være årstal.
    idxEnd = dinStreng.length();
    if ( (idxEnd != idxBeg+2) && (idxEnd != idxBeg+4) ) {
        return null;  // failed: forkert antal cifre i årstallet
    }
    int aar = laesTal ( dinStreng.substring(idxBeg,idxEnd), 0, 9999 );
    if ( aar < 0 ) {
        return null;  // failed: ugyldigt årstal.
    }
    if ( aar < 100 ) {
        // konverter til 4cifret årstalværdi efter den regel du nu har valgt at bruge
    }
    Calendar resultat = new GregorianCalendar();
    resultat.setLenient( true ); // en 'gal' dato som 30-februar bliver lavet som 2-marts
    resultat.set( aar, maaned-1, dato ); //NB måske time.minut,sekund,... skal nulstilles.
                  // NB: en 'gal' dato som 30-februar bliver lavet som 2-marts
    return resultat;
} //end checkDatoStreng( String ) -> Calendar OR null


    static TestDatocheck dag = null;
   
    public static void test( String testStreng ) {
      Calendar d = dag.checkDatoStreng( testStreng );
      if ( d == null ) {
          System.out.println( testStreng +" giver fejl" );
      } else {
          System.out.println( testStreng +" er OK " +d.getTime() );
      }
    }
    public static void main( String[] argv ) {
      dag = new TestDatocheck();
      test( "12-34-1234" );
      test( "12/4/34" );
      test( "20.5.50" );
      test( "20-5-1950" );
      test( "12/4/234" );
    } //end main()


} //endclass TestDatocheck

mvh JakobA
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