2017-06-28 8 views
1

Ich habe den folgenden Code für die Aufnahme eines Datums in Form einer Zeichenfolge yyyy-MM-dd HH:mm:ss (UTC-Zeitzone) und die Umwandlung in EEEE d(st, nd, rd, th) MMMM yyyy HH:mm (Standardzeitzone des Geräts).Datum analysieren und formatieren

Allerdings ist mein Problem mit der Art, wie ich es getan habe, der Code sieht chaotisch und ineffizient. Gibt es eine Möglichkeit, das zu erreichen, was ich möchte, ohne das gleiche Datum so oft zu bilden und zu analysieren, um es effizienter zu machen? Oder irgendwelche anderen Verbesserungen?

Vorzugsweise Android API-Ebene unterstützt 14.


String inputExample = "2017-06-28 22:44:55"; 

//Converts UTC to Device Default (Local) 
private String convertUTC(String dateStr) { 
    try { 
     SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
     df.setTimeZone(TimeZone.getTimeZone("UTC")); 
     Date temp = df.parse(dateStr); 
     df.setTimeZone(TimeZone.getDefault()); 
     String local = df.format(temp); 
     Date localDate = df.parse(dateStr); 
     SimpleDateFormat outputDF1 = new SimpleDateFormat("EEEE "); 
     SimpleDateFormat outputDF2 = new SimpleDateFormat(" MMMM yyyy HH:mm"); 
     return outputDF1.format(temp) + prefix(local) + outputDF2.format(temp); 
    } catch(java.text.ParseException pE) { 
     Log.e("", "Parse Exception", pE); 
     return null; 
    } 
} 

private String prefix(String dateStr) { 
    try { 
     SimpleDateFormat outputDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
     Date temp = outputDF.parse(dateStr); 
     SimpleDateFormat df = new SimpleDateFormat("d"); 
     int d = Integer.parseInt(df.format(temp)); 
     if(1 <= d && d <= 31) { 
      if(11 <= d && d <= 13) 
       return d + "th"; 
      switch (d % 10) { 
       case 1: return d + "st"; 
       case 2: return d + "nd"; 
       case 3: return d + "rd"; 
       default: return d + "th"; 
      } 
     } 
     Log.e("", "Null Date"); 
     return null; 
    } catch(java.text.ParseException pE) { 
     Log.e("", "Parse Exception", pE); 
     return null; 
    } 
} 
+7

Ich stimme für das Schließen dieser Frage als Off-Topic, weil es auf [codereview.se] gehört. – shmosel

+0

@smossel Vielen Dank, dass Sie darauf hingewiesen haben. Ich poste es dort – Dan

+0

Sie müssen Ihren Code profilieren, um herauszufinden, was schlechte Leistung verursacht. Was den "unordentlichen" Teil anbelangt - nun, java.util.date APIs werden allgemein als "unordentlich" betrachtet, es gibt nicht viel, was Sie tun können. Refactor den Code, um Wege zu finden, um es sauberer zu machen. Stellen Sie sicher, dass Sie eine kugelsichere Suite von Komponententests haben, bevor Sie mit dem Refactoring beginnen. – Egor

Antwort

2

Mit SimpleDateFormat gibt es wahrscheinlich zu verbessern nicht viel. Da Ihr Ausgabeformat EEEE (Wochentag) und MMMM (Monatsname) hat, müssen Sie das Datum analysieren, um die Werte für diese zu kennen. Ohne einen Datumsformatierer zu verwenden, müssen Sie viele if 's machen, um die jeweiligen Namen für jeden Wert zu erhalten.


In Android, als Alternative zu SimpleDateFormat, können Sie die ThreeTen Backport, eine große Rückportierung für neue Java-8s Datum/Zeit-Klassen verwenden, zusammen mit den ThreeTenABP (mehr darüber, wie es zu benutzen here). Alle Klassen sind unterhalb des org.threeten.bp Pakets. Im folgenden Code auch Locale.ENGLISH Ich verwende, sonst wird es die Standardeinstellung des Systems verwenden (wie ich nicht Englisch ist und ich Ihnen gehe davon ist):

String inputExample = "2017-06-28 22:44:55"; 
// parser for input 
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH); 
// parse the date and set to UTC 
ZonedDateTime z = LocalDateTime.parse(inputExample, parser).atZone(ZoneOffset.UTC); 

// map of custom values - map each numeric value to its string with suffix (st, nd...) 
Map<Long, String> textLookup = new HashMap<Long, String>(); 
for (int i = 1; i <= 31; i++) { 
    String suffix = ""; 
    switch (i) { 
    case 1: 
    case 21: 
    case 31: 
     suffix = "st"; 
     break; 
    case 2: 
    case 22: 
     suffix = "nd"; 
     break; 
    case 3: 
    case 23: 
     suffix = "rd"; 
     break; 
    default: 
     suffix = "th"; 
    } 
    textLookup.put((long) i, i + suffix); 
} 
// output formatter 
DateTimeFormatter fmt = new DateTimeFormatterBuilder() 
    // day of week 
    .appendPattern("EEEE ") 
    // append day with suffix (use map of custom values) 
    .appendText(ChronoField.DAY_OF_MONTH, textLookup) 
    // rest of pattern 
    .appendPattern(" MMMM yyyy HH:mm") 
    // create formatter with English locale 
    .toFormatter(Locale.ENGLISH); 

// print date, convert it to device default timezone 
System.out.println(fmt.format(z.withZoneSameInstant(ZoneId.systemDefault()))); 

Der Ausgang wird sein:

mittwoch 28. Juni 2017 19.44

Die Zeit bis zum 19:44 wurde eingestellt, weil meine Standard-Zeitzone America/Sao_Paulo ist (in UTC-03: 00).

Nicht sicher, ob es weniger chaotisch genug für Sie ist, aber zumindest IMO ist es viel klarer als SimpleDateFormat. Es wurden nur 2 Formatierer erstellt (einer für die Ausgabe, ein anderer für die Ausgabe). Natürlich gibt es die textLookup Karte, aber es hat nur 31 Einträge und die Formatierer können auch wiederverwendet werden.

Und SimpleDateFormat is not thread safe, während the new API is.

Verwandte Themen