2017-06-28 12 views
1

文字列yyyy-MM-dd HH:mm:ss(UTCタイムゾーン)の形式で日付を取得し、それをEEEE d(st, nd, rd, th) MMMM yyyy HH:mm(デバイスのデフォルトのタイムゾーン)にするためのコードを用意しました。解析と書式の日付

しかし、私のやり方の問題は、コードが乱雑で非効率的に見えることです。より効率的にするために同じ日付を何度もフォーマットし解析することなく、私が望むものを達成する方法はありますか?その他の改善点は?

は、好ましくは改善するために多くはおそらくないのAndroid APIレベルにSimpleDateFormat 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

[codereview.se]に属しているため、この質問を議論の対象外としています。 – shmosel

+0

@shmoselそれを指摘してくれてありがとう。私はそこに投稿します – Dan

+0

あなたのコードをプロファイリングして、パフォーマンスの低下の原因を突き止める必要があります。 「面倒な」部分に関しては、java.util.date APIは広く「厄介」とみなされています。多くのことができません。コードをリファクタリングして、よりクリーンな方法を見つけてください。リファクタリングを開始する前に、単体テストの包括的なスイートがあることを確認してください。 – Egor

答えて

2

をサポートします。あなたの出力形式はEEEE(曜日)とMMMM(月名)であるため、それらの値を知るためには日付を解析する必要があります。日付フォーマッタを使用しないで、ifの多くの各値のそれぞれの名前を取得する必要があります。アンドロイドで


SimpleDateFormatに代わるものとして、あなたは一緒に ThreeTenABPThreeTen Backport、Javaの8の新しい日付/時間の授業のための偉大なバックポート、(それ hereを使用する方法の詳細)を使用することができます。

すべてのクラスは、org.threeten.bpパッケージの下にあります。

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()))); 

出力は次のようになります:

私も(私が英語ではないと私はあなたをされたと仮定しているとして)それ以外の場合は、システムのデフォルトを使用します、 Locale.ENGLISHを使用しています次のコードで

水曜日2017年6月28日19時44

私のデフォルトのタイムゾーンは(UTC-03で:00America/Sao_Pauloであるため、時間が19:44に設定しました。

あなたにとってはそれほど面倒ではありませんが、少なくともIMOではSimpleDateFormatよりはるかに明確です。ちょうど2つのフォーマッタが作成されました(1つは出力用、もう1つは出力用)。もちろん、textLookupマップがありますが、それはわずか31エントリしかなく、フォーマッタも再利用できます。

およびSimpleDateFormat is not thread safeであり、the new API isである。