2Danke
ERLEDIGT
JA
JA
ANTWORTEN
9
9
ZUGRIFFE
760
760
EMPFEHLEN
-
Einen wunderschönen guten Abend,
Für die Sortierung von Datumswerten in einer Tabelle betrachte ich einen entsprechenden String, in dem ich alle nicht numerischen Zeichen als Trennzeichen interpretiere und dann die Zahlen einzeln auswerte.
Das funktioniert auch soweit. Allerdings erscheint mir meine Methode aus dem Datums-String ein auswertbares Array zu machen etwas umständlich.
Beispielbelegung von date = "01.06.2010 - 23:45 Uhr"
Ziel-Array value = String[] { "01", "06", "2010", "23", "45" }
Meine aktuelle Herangehensweise:
Code java:1
String[] value = date.replaceAll("[^0-9]*[^0-9]", " ").trim().split(" ");
Liefert noch ein leeres Element am Ende:
Code java:1
String[] value = date.split("[^0-9]*[^0-9]");
Gibt es einen einfacheren Weg voran- bzw. nachgestellte Trennzeichen zu ignorieren?
Mein Ergebnis-Array soll ja nach Möglichkeit keine Leer-Elemente enthalten...
Viele Grüße
Carron
-
04.06.10 01:18 #2
- Registriert seit
- Aug 2005
- Ort
- Karlsruhe (Baden-Württemberg)
- Beiträge
- 900
Dumme Frage. warum lässt du das Datum nicht einfach von bereits bestehenden Bibliotheken parsen?
DateTimeFormatter(JodaTime), SimpledateFormat (JRE - nicht multithreaded), FastDateFormat (apache commons)Wäre super wenn ihr euren Code in dieser Form einfügt:
[java]System.out.println("Hello World");[/java]Code java:1
System.out.println("Hello World");
Für erledigte Threads dürft ihr den "erledigt"-Button anklicken!
Über Dank freut sich jeder, der euch geholfen hat - ein Klick auf "Danke" kostet ja nicht mal was
Blog: http://javaeffective.wordpress.com/
-
Hallo Anime-Otaku,
eigentlich ging es mir ja nur allgemein um einen Ersatz zu
String.replace(regEx, " ").trim().split(" ")
da ich leider nicht in jedem Fall auf die Leerzeichen in den übrigen Strings verzichten kann und mich dann mit substring() herumschlagen muss.
Aber zu deinem Einwand, warum ich in diesem konkreten Beispiel nicht das Datum parse:
In einer Spalte mit der Datums-Sortieroption lasse ich mehrere Pattern zu. Anzahl und Art der Trennzeichen sind mir dabei egal ([^0-9]*[0-9]).
Beispielsweise:
Code java:1 2 3 4 5 6 7 8 9 10
// date format: dd. private static final String FORMAT_DD = "%1$td."; // date format: dd.mm. private static final String FORMAT_DDMM = "%1$td.%1$tm."; // date format: dd.mm.YYYY private static final String FORMAT_DDMMYYYY = "%1$td.%1$tm.%1$tY"; // date format: dd.mm. HH:MM private static final String FORMAT_DDMM_HHMM = "%1$td.%1$tm. %1$tH:%1$tM"; // date format: dd.mm.YYYY HH:MM private static final String FORMAT_DDMMYYYY_HHMM = "%1$td.%1$tm.%1$tY %1$tH:%1$tM";
um jedoch einen entsprechenden Formatter nutzen zu können brauche ich jeweils das eindeutig anwendbare Pattern. Ich habe mir hier die Brücke geschlagen und es (nach Entfernung der Leer-Elemente auf oben genannte Art und Weise) an der Anzahl der Segmente festgemacht, da die fünf zulässigen Pattern daran eindeutig zu unterscheiden sind. Anschließend vergleiche ich dann die enthaltenen Integer-Werte. Darüber hinaus sollen auch Einträge, die unterschiedliche Pattern erfüllen, einander gegenübergestellt werden und der Eintrag mit der höchsten Spezifizierung (mehr Segmente) wird automatisch als größer angesehen.. Das könnte mit dem entsprechenden Datums-Parser natürlich eleganter von Statten gehen.
Beispiel aktueller Sortierung (aufsteigend):
Code :1 2 3 4 5 6 7 8 9 10 11 12
15. 21. 13.10. 09.12. 25.05.2009 24.05.2010 12.06. - 14:23 Uhr 12.06. - 14:29 Uhr 12.06. - 15:16 Uhr 28.11. - 09:20 Uhr 25.04.2008 - 22:16 Uhr 12.02.2010 - 14:10 Uhr
Ich meine: die Pattern können mittels regulärer Ausdrücke auf ihre Anwendbarkeit geprüft werden, da die Segmentanzahl eindeutig über das Format Aufschluss gibt. Ich hatte allerdings bisher nur mit dem SimpleDateFormatter zu tun, der mir in Sachen Pattern nicht variabel genug ist...
Das erscheint mir aber immer noch etwas behäbig:
Code java:1 2 3 4 5 6 7 8 9
private static final String REGEX_DATETIME_DD = "[^0-9]*[0-9][0-9][^0-9]*"; private static final String REGEX_DATETIME_DDMM = REGEX_DATETIME_DD + "[^0-9][0-9][0-9][^0-9]*"; private static final String REGEX_DATETIME_DDMMYYYY = REGEX_DATETIME_DDMM + "[^0-9][0-9][0-9][0-9][0-9][^0-9]*"; private static final String REGEX_DATETIME_DDMM_HHMM = REGEX_DATETIME_DDMM + "[^0-9][0-9][0-9][^0-9]*" + "[^0-9][0-9][0-9][^0-9]*"; private static final String REGEX_DATETIME_DDMMYYYY_HHMM = REGEX_DATETIME_DDMMYYYY + "[^0-9][0-9][0-9][^0-9]*" + "[^0-9][0-9][0-9][^0-9]*";
In welchem Datums-Parser kann ich denn eine beliebige Anzahl nicht-numerischer Zeichen im Pattern übergeben? (Bei den drei von dir genannten konnte ich das noch nicht erkennen.)
Quasi in die Richtung [B[^0-9]*dd[^0-9]*[^0-9]mm[^0-9]*[^0-9]YYYY[^0-9]*[^0-9]HH[^0-9]*[^0-9]MM[^0-9]*[/B].
Grüße
Carron
EDIT: wenn ich die beliebigen Zeichen vorher durch ein Einheitstrennzeichen ersetze, kann ich zwar das SimpleDateFormat verwenden, aber das würde mich wieder zu meiner ursprünglichen Frage führen
-
04.06.10 09:11 #4twagi1232010 Tutorials.de Gastzugang
Hallo,
wenn Du Dein Datum nicht unbedingt über reguläre Ausdrücke parsen musst, könntest Du Dir die Methode zum Parsen auch selber schreiben.
In etwa sowas wie dieses hier:
Code java:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
public Collection<String> parseDigits(String aText) { Collection<String> result = new ArrayList<String>(); StringBuffer buffer = new StringBuffer(); for (int i = 0; i < aText.length(); i++) { char charAt = aText.charAt(i); if(Character.isDigit(charAt)) { buffer.append(charAt); } else if(buffer.length() > 0) { result.add(buffer.toString()); buffer.delete(0, buffer.length()); } } return result; }
Vielleicht hilft Dir das weiter.
Grüße
twagi
-
04.06.10 09:32 #5
- Registriert seit
- Aug 2005
- Ort
- Karlsruhe (Baden-Württemberg)
- Beiträge
- 900
Wenn ich dich richtig verstanden habe dann kannst du durch das Pattern bereits erkennen, um welches Datumsformat es sich handelt? Wenn das so ist, dann frag doch mit Pattern ab, ob das dieses Datumsformat ist und dann kannst du den spezifischen Parser verwenden.
Wäre super wenn ihr euren Code in dieser Form einfügt:
[java]System.out.println("Hello World");[/java]Code java:1
System.out.println("Hello World");
Für erledigte Threads dürft ihr den "erledigt"-Button anklicken!
Über Dank freut sich jeder, der euch geholfen hat - ein Klick auf "Danke" kostet ja nicht mal was
Blog: http://javaeffective.wordpress.com/
-
Entschuldigt bitte den langen (und vor allem nicht wirklich aussagekräftigen) Post zuvor.

Ich habe jetzt deinen Vorschlag umgesetzt und fahre mit dem SimpleDateFormat auch ganz gut.
Abgesehen von den zusätzlichen Konstanten hat das meinen vorherigen Code ziemlich entschlackt.
Code java: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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
/** * Regular expression representing all characters to be treated as * separators in <code>COMPARE_DATETIME</code> mode.<br> * Current setting: all non-numeric characters</br> */ private static final String REGEX_DATETIME_SEPARATOR = "[^0-9]*[^0-9]"; private static final String REGEX_DATETIME_DD = "[^0-9]*[0-9][0-9][^0-9]*"; private static final SimpleDateFormat FORMAT_DATETIME_DD = new SimpleDateFormat("dd"); private static final String REGEX_DATETIME_DDMM = REGEX_DATETIME_DD + "[^0-9][0-9][0-9][^0-9]*"; private static final SimpleDateFormat FORMAT_DATETIME_DDMM = new SimpleDateFormat("dd MM"); private static final String REGEX_DATETIME_DDMMYYYY = REGEX_DATETIME_DDMM + "[^0-9][0-9][0-9][0-9][0-9][^0-9]*"; private static final SimpleDateFormat FORMAT_DATETIME_DDMMYYYY = new SimpleDateFormat("dd MM yyyy"); private static final String REGEX_DATETIME_DDMM_HHMM = REGEX_DATETIME_DDMM + "[^0-9][0-9][0-9][^0-9]*" + "[^0-9][0-9][0-9][^0-9]*"; private static final SimpleDateFormat FORMAT_DATETIME_DDMM_HHMM = new SimpleDateFormat("dd MM HH mm"); private static final String REGEX_DATETIME_DDMMYYYY_HHMM = REGEX_DATETIME_DDMMYYYY + "[^0-9][0-9][0-9][^0-9]*" + "[^0-9][0-9][0-9][^0-9]*"; private static final SimpleDateFormat FORMAT_DATETIME_DDMMYYYY_HHMM = new SimpleDateFormat("dd MM yyyy HH mm"); /** * Compares the values of the given column in the two specified entries as * date strings in one of the following forms: <code>DD.</code>, * <code>DD.MM.</code>, <code>DD.MM.YYYY</code>, * <code>DD.MM.YYYY_hh:mm</code>, <code>DD.MM_hh:mm</code><br> * Every character that is no number is considered to be a separator.<br> * The single values are interpreted as <code>Integer</code>s. * * @param targetColumn * selected column * @param itemOne * first entry to compare * @param itemTwo * second entry to compare * @return first entry is smaller, bigger or equals second entry */ int compareDateTime(TableColumn targetColumn, TableItem itemOne, TableItem itemTwo) { int result; // get current position of the target column final int columnIndex = getColumnIndex(targetColumn); try { // read contained dates and compare them result = parseDate(itemOne.getText(columnIndex)).compareTo( parseDate(itemTwo.getText(columnIndex))); if (SorTable.this.lastDescendingColumn == targetColumn) { /* * column was already sorted in descending order: invert sort * direction */ result *= -1; } } catch (final ParseException ex) { /* * at least one of the contained strings do not fit on any of the * given date formats */ result = compareText(targetColumn, itemOne, itemTwo); } return result; } /** * Reads the given <code>String</code> expecting one of the given date * formats:<br> * <code>DD.</code>, <code>DD.MM.</code>, <code>DD.MM.YYYY</code>, * <code>DD.MM.YYYY_hh:mm</code> or <code>DD.MM._hh:mm</code></br> All * non-numeric characters are treated to be separators. Empty segments are * ignored. * * @param dateString * date <code>String</code> to parse * @return contained date value * @throws ParseException * failed to parse given format or <code>String</code> did not * match any allowed pattern */ private Date parseDate(final String dateString) throws ParseException { // replace separators with whitespaces to use trim() final String cleanValue = dateString.replaceAll( REGEX_DATETIME_SEPARATOR, " ").trim(); // get the Formatter for the matching pattern SimpleDateFormat formatter; if (Pattern.matches(REGEX_DATETIME_DD, cleanValue)) { formatter = FORMAT_DATETIME_DD; } else if (Pattern.matches(REGEX_DATETIME_DDMM, cleanValue)) { formatter = FORMAT_DATETIME_DDMM; } else if (Pattern.matches(REGEX_DATETIME_DDMMYYYY, cleanValue)) { formatter = FORMAT_DATETIME_DDMMYYYY; } else if (Pattern.matches(REGEX_DATETIME_DDMM_HHMM, cleanValue)) { formatter = FORMAT_DATETIME_DDMM_HHMM; } else if (Pattern.matches(REGEX_DATETIME_DDMMYYYY_HHMM, cleanValue)) { formatter = FORMAT_DATETIME_DDMMYYYY_HHMM; } else { // does not fit on any given pattern throw new ParseException(dateString, 0); } // parse the contained date return formatter.parse(cleanValue); }
Vielen Dank und Grüße
CarronGeändert von Carron (04.06.10 um 10:58 Uhr) Grund: Einrückungen im Code nachgeholt
-
04.06.10 11:24 #7
- Registriert seit
- Aug 2005
- Ort
- Karlsruhe (Baden-Württemberg)
- Beiträge
- 900
Ich zitiere mich ungern selbst, aber SimpleDateFormat ist nicht multithreaded-fähig (siehe auch API oder den source). Daher wenn formatter.parse(cleanValue); von mehreren Threads parallel ausgeführt werden kann, kommt es zu seltsamen Ergebnissen (intern wird beim Ausführen von parse ein Calendar-Objekt aufgebaut). Am einfachsten machst du immer einen neuen SimpleDateFormat, der Performanceverlust ist vernachlässigbar oder wenn es nur selten parallel läuft mach einfach ein synchronized drum herum.
Oder du greifst auf eine der anderen genannten libs zurück. Besonders wenn du viel mit Zeiten hantierst ist JodaTime stark zu empfehlen gegenüber der Java internen Zeit API.Geändert von Anime-Otaku (04.06.10 um 11:28 Uhr)
Wäre super wenn ihr euren Code in dieser Form einfügt:
[java]System.out.println("Hello World");[/java]Code java:1
System.out.println("Hello World");
Für erledigte Threads dürft ihr den "erledigt"-Button anklicken!
Über Dank freut sich jeder, der euch geholfen hat - ein Klick auf "Danke" kostet ja nicht mal was
Blog: http://javaeffective.wordpress.com/
-
04.06.10 15:27 #8
Hallo, eins ist mir nicht ganz klar:
Code java:1
private static final String REGEX_DATETIME_SEPARATOR = "[^0-9]*[^0-9]";
Wieso setzt du "[^0-9]" nochmal hinter "[^0-9]*"? Willst du damit ausdrücken, dass mindestens ein nicht nummerisches Zeichen vorkommen soll? Wenn ja, es gibt auch ein Zeichen für "mindestens 1x" und das ist "+". D.h. man schreibe "[^0-9]+"
Ebenso z.B. ...
Code java:1
private static final String REGEX_DATETIME_DDMMYYYY = REGEX_DATETIME_DDMM + "[^0-9][0-9][0-9][0-9][0-9][^0-9]*";
Du hast 4x hintereiander "[0-9]". Folgender Ausdruck erfordert deine Zeichenauswahl 4x: "[0-9]{4}".
Also deine Ausdrücke sind nicht falsch, aber es geht kürzer...
Siehe auch http://de.wikipedia.org/wiki/Regul%C3%A4rer_AusdruckGeändert von HonniCilest (04.06.10 um 15:30 Uhr)
Jeder Fehler, aus dem wir lernen, ist ein Erfolg...
...Aber mach' nicht den Fehler, nicht aus deinen Fehlern zu lernen.
-
@HonniCilest:
Danke für die Hinweise, ich habe nur in der Eile einfach das Ganze zusammengehauen und wollte mir das Kürzen für später überlassen (da ich mir im Zug nicht mehr der Meta-Notationen bewusst war und es sollte halt funktionieren
).
@Anime-Otaku:
Auch dir vielen Dank für den Einwand. Da die compareDateTime()-Methode zwar nur vom Tabellen-Comparator aufgerufen wird bin ich fast immer ohne Parallellläufigkeit unterwegs, aber sicherheitshalber ist das Ganze aber nun auch synchronized. Um mir die Einführung von JodaTime zu sparen, bleibe ich in diesem Fall beim SimpleDateFormat. Da das nur für relativ kleine Tabellen gemacht wird, ist das nicht so zeitkritisch.
Vielleicht kannst du mir aber bitte nochmal sagen inwiefern JodaTime eher zu empfehlen ist. Ist es nur sauberer oder auch performanenter? Wenn letzteres der Fall ist: spürbar schneller?
Mein aktueller Stand sieht jedenfalls folgendermaßen aus:
Code java: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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
/** * Regular expression representing all characters to be treated as * separators in <code>COMPARE_DATETIME</code> mode.<br> * Current setting: all non-numeric characters */ private static final String REGEX_DATETIME_SEPARATOR = "[\\D]+"; private static final String REGEX_DATETIME_DD = "[\\D]*[\\d]{2}[\\D]*"; private static final SimpleDateFormat FORMAT_DATETIME_DD = new SimpleDateFormat( "dd"); private static final String REGEX_DATETIME_DDMM = "[\\D]*[\\d]{2}" + "[\\D]+[\\d]{2}[\\D]*"; private static final SimpleDateFormat FORMAT_DATETIME_DDMM = new SimpleDateFormat( "dd MM"); private static final String REGEX_DATETIME_DDMMYYYY = "[\\D]*[\\d]{2}" + "[\\D]+[\\d]{2}" + "[\\D]+[\\d]{4}[\\D]*"; private static final SimpleDateFormat FORMAT_DATETIME_DDMMYYYY = new SimpleDateFormat( "dd MM yyyy"); private static final String REGEX_DATETIME_DDMM_HHMM = "[\\D]*[\\d]{2}" + "[\\D]+[\\d]{2}" + "[\\D]+[\\d]{2}" + "[\\D]+[\\d]{2}[\\D]*"; private static final SimpleDateFormat FORMAT_DATETIME_DDMM_HHMM = new SimpleDateFormat( "dd MM HH mm"); private static final String REGEX_DATETIME_DDMMYYYY_HHMM = "[\\D]*[\\d]{2}" + "[\\D]+[\\d]{2}" + "[\\D]+[\\d]{4}" + "[\\D]+[\\d]{2}" + "[\\D]+[\\d]{2}[\\D]*"; private static final SimpleDateFormat FORMAT_DATETIME_DDMMYYYY_HHMM = new SimpleDateFormat( "dd MM yyyy HH mm"); /** * Compares the values of the given column in the two specified entries as * date strings in one of the following forms: <code>DD.</code>, * <code>DD.MM.</code>, <code>DD.MM.YYYY</code>, * <code>DD.MM.YYYY_hh:mm</code>, <code>DD.MM_hh:mm</code><br> * Every character that is no number is considered to be a separator.<br> * The single values are interpreted as <code>Integer</code>s. * * @param targetColumn * selected column * @param itemOne * first entry to compare * @param itemTwo * second entry to compare * @return first entry is smaller, bigger or equals second entry */ int compareDateTime(TableColumn targetColumn, TableItem itemOne, TableItem itemTwo) { int result; // get current position of the target column final int columnIndex = getColumnIndex(targetColumn); try { // read contained dates and compare them result = parseDate(itemOne.getText(columnIndex)).compareTo( parseDate(itemTwo.getText(columnIndex))); if (SorTable.this.lastDescendingColumn == targetColumn) { /* * column was already sorted in descending order: invert sort * direction */ result *= -1; } } catch (final ParseException ex) { /* * at least one of the contained strings do not fit on any of the * given date formats */ result = compareText(targetColumn, itemOne, itemTwo); } return result; } /** * Reads the given <code>String</code> expecting one of the given date * formats:<br> * <code>DD.</code>, <code>DD.MM.</code>, <code>DD.MM.YYYY</code>, * <code>DD.MM.YYYY_hh:mm</code> or <code>DD.MM._hh:mm</code></br> All * non-numeric characters are treated to be separators. Empty segments are * ignored. * * @param dateString * date <code>String</code> to parse * @return contained date value * @throws ParseException * failed to parse given format or <code>String</code> did not * match any allowed pattern */ private Date parseDate(final String dateString) throws ParseException { // replace separators with whitespaces to use trim() final String cleanValue = dateString.replaceAll( REGEX_DATETIME_SEPARATOR, " ").trim(); // get the Formatter for the matching pattern SimpleDateFormat formatter; if (Pattern.matches(REGEX_DATETIME_DD, cleanValue)) { formatter = FORMAT_DATETIME_DD; } else if (Pattern.matches(REGEX_DATETIME_DDMM, cleanValue)) { formatter = FORMAT_DATETIME_DDMM; } else if (Pattern.matches(REGEX_DATETIME_DDMMYYYY, cleanValue)) { formatter = FORMAT_DATETIME_DDMMYYYY; } else if (Pattern.matches(REGEX_DATETIME_DDMM_HHMM, cleanValue)) { formatter = FORMAT_DATETIME_DDMM_HHMM; } else if (Pattern.matches(REGEX_DATETIME_DDMMYYYY_HHMM, cleanValue)) { formatter = FORMAT_DATETIME_DDMMYYYY_HHMM; } else { // does not fit on any given pattern throw new ParseException(dateString, 0); } synchronized (formatter) { // parse the contained date return formatter.parse(cleanValue); } }
Danke.
CarronGeändert von Carron (05.06.10 um 11:47 Uhr)
-
05.06.10 12:43 #10
- Registriert seit
- Aug 2005
- Ort
- Karlsruhe (Baden-Württemberg)
- Beiträge
- 900
http://joda-time.sourceforge.net/index.html da steht das direkt auf der Hauptseite

Leider muss ich aber gestehen bisher selbst noch nicht groß in den Genuss von JodaTime gekommen zu sein. Wir benutzen traurigerweise in unserem Produkt in der Firma immer noch Calendar-Objekte zum Speichern von Zeitstempeln und wie es so ist hat man mal nicht eben Zeit die Datenstruktur komplett zu ändern (man müsste auch andere Datenstruktur Sachen ändern). Calendar-Objekte brauchen afaik über 400 byte Speicher!
Und Privat hab ich schon ein wenig damit rumgespielt und von einigen erfahreren Java-Entwicklern wird das auch immer wieder empfohlen.
Wäre super wenn ihr euren Code in dieser Form einfügt:
[java]System.out.println("Hello World");[/java]Code java:1
System.out.println("Hello World");
Für erledigte Threads dürft ihr den "erledigt"-Button anklicken!
Über Dank freut sich jeder, der euch geholfen hat - ein Klick auf "Danke" kostet ja nicht mal was
Blog: http://javaeffective.wordpress.com/
Ähnliche Themen
-
Animationsgeschwindigkeit am Anfang und Ende zu langsam
Von Nils_13 im Forum Cinema 4DAntworten: 2Letzter Beitrag: 03.04.09, 11:51 -
Der Anfang vom Ende
Von mAu im Forum FotografieAntworten: 7Letzter Beitrag: 26.10.07, 00:29 -
slidemenu am anfang und ende anhalten
Von PeterMcB im Forum Flash PlattformAntworten: 4Letzter Beitrag: 01.12.06, 12:47 -
Anfang und Ende definieren?
Von asdfg im Forum PHPAntworten: 9Letzter Beitrag: 03.04.06, 17:30 -
Objekt am Anfang und Ende langsamer
Von Xo-mate im Forum Cinema 4DAntworten: 12Letzter Beitrag: 05.03.05, 20:23





Zitieren
Login




