2017-06-07 4 views
2

お客様からの日時フォーマットを受け入れるアプリケーションがあります。Java 8の日付時刻APIを使用する場合、AM/PM記号を自分のアルファベットに変更する方法

最近、スレッドセーフであるため、Java 8の新しい日付時刻APIへの移行が開始されました。 AとPをAM & PM文字列と見なすように設定しているフォーマッタを準備する前に、以下のコードを見てください。 &からフォーマッタを取得します。以下のロジックを適用して日付時刻を表示するだけです。

String[] AMPM = new String[2]; 
AMPM[0] = "A"; 
AMPM[1] = "P"; 
DateFormatSymbols dfs = new DateFormatSymbols(locale); 
dfs.setAmPmStrings(AMPM); 
sdf = new SimpleDateFormat(format, dfs); 

新しいJava 8の日付時刻APIでは、これを定義する方法はありません。しかし、いくつかのグーグルの後に私はDateTimeFormatterBuilderを使用しなければならないことがわかりますが、これはパターンを自分で構築している場合にのみ役に立ちます。ここでは顧客から完全な日付のパターンを受け取ります。カスタム値でのマップを取るDateTimeFormatterBuilder.appendText()方法を使用できるJava 8

+0

これは前に頼まれました。私は正確なタイトルや言葉を覚えていませんが、検索に行きます。 –

+0

受け取っているパターンは常に同じですか?それは常に午前/午後のフィールドを持っていますか? –

+0

[この回答](https://stackoverflow.com/a/24004917/5772882)が役立ちます。質問は解析についてですが、私は解決策がフォーマットにも役立つと思います。 –

答えて

3

使用してこれを行う方法の

任意のポインタ。

javadocによると、フィールドAMPM_OF_DAYAMの値0PMため1を持つことができるので、あなただけのこれらの値を使用してマップを作成し、フォーマッタに渡し:

import java.time.format.DateTimeFormatter; 
import java.time.format.DateTimeFormatterBuilder; 
import java.time.temporal.ChronoField; 
import java.time.LocalTime; 

// create map with custom values (0=AM, 1=PM, mapping to values "A" and "P") 
Map<Long, String> map = new HashMap<>(); 
map.put(0L, "A"); // AM mapped to "A" 
map.put(1L, "P"); // PM mapped to "P" 

DateTimeFormatter formatter = new DateTimeFormatterBuilder() 
    // hour/minute/second (change to whatever pattern you need) 
    .appendPattern("hh:mm:ss ") 
    // use the mapped values 
    .appendText(ChronoField.AMPM_OF_DAY, map) 
    // create formatter 
    .toFormatter(); 

// testing 
System.out.println(formatter.format(LocalTime.of(10, 30, 45))); // 10:30:45 A 
System.out.println(formatter.format(LocalTime.of(22, 30, 45))); // 10:30:45 P 

すると出力がされます:

10時30分45秒
10時30分45秒P

そしてそれはまたStringを解析するために動作します:

System.out.println(LocalTime.parse("10:20:30 A", formatter)); // 10:20:30 
System.out.println(LocalTime.parse("10:20:30 P", formatter)); // 22:20:30 

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

10時20分30秒
夜09時20分30秒


パターンを制御しない場合は、文字012を探すことができます(AM/PMフィールドに対応するパターン)、カスタムバージョンで置き換えます。

1つの選択肢は、区切り文字としてaを使用して、フォーマットStringを分割することです、そしてあなたは、パターンの残りの部分を失うことはありません:

// format with day/month/year hour:minute:second am/pm timezone 
String format = "dd/MM/yyyy hh:mm:ss a z"; 

// split the format ("a" is the AM/PM field) 
String[] formats = format.split("a"); 

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder() 
    // first part of the pattern (everything before "a") 
    .appendPattern(formats[0]) 
    // use the AM/PM mapped values 
    .appendText(ChronoField.AMPM_OF_DAY, map); 

// if there's something after the "a", add it 
if (formats.length > 1) { 
    builder.appendPattern(formats[1]); 
} 

// create formatter 
DateTimeFormatter formatter = builder.toFormatter(); 

//test 
ZonedDateTime z = ZonedDateTime.of(2017, 5, 1, 10, 20, 30, 0, ZoneId.of("America/Sao_Paulo")); 
// AM replaced by "A" 
System.out.println(formatter.format(z)); // 01/05/2017 10:20:30 A BRT 

aが先頭にある場合や、このアルゴリズムはまた、作品またはaがない場合(この場合は、最後に追加します。存在しない場合は、追加する必要があるかどうかはわかりません)。フォーマットはaが含まれていない場合は、それを追加しないように

// "a" in the end 
String format = "hh:mm:ss a"; 
DateTimeFormatter formatter = // use same code above 
System.out.println(formatter.format(LocalTime.of(15, 30))); // 03:30:00 P 

// "a" in the beginning 
String format = "a hh:mm:ss"; 
DateTimeFormatter formatter = // use same code above 
System.out.println(formatter.format(LocalTime.of(15, 30))); // P 03:30:00 

// no "a" (field is added in the end) 
String format = "HH:mm:ss"; 
DateTimeFormatter formatter = // use same code above 
System.out.println(formatter.format(LocalTime.of(15, 30))); // 03:30:00P 

あなたは、いくつかの改善を行うことができます(またはその前にスペースを追加)、または何でもしたいです。


PS:このコードは"dd/MM/yyyy 'at' hh:mm:ss a"のようなリテラル('内のテキスト)を処理しません(「時」リテラルで、交換/削除すべきではありません)。

私は正規表現の専門家(私はそれがすべてのケースで動作している場合は100%わからない)ないんだけど、あなたはこのような何かを行うことができます。

String[] formats = format.split("(?<!\'[^\']{0,20})a|a(?![^\']{0,20}\')"); 

引用された内部でこの正規表現はaを無視しますテキスト。 lookaheadとlookbehinds((?パターン)は*を受け付けないため、{0,20}の限定記号を使用する必要があります。したがって、 "a"の前後に引用符で囲まれたテキストが最大20文字(ちょうどあなたが考えるものユースケースに最適です)。

一部のテスト:

String format = "\'Time: at\' hh:mm:ss a"; 
DateTimeFormatter formatter = // use same code above, but with the modified regex split 
System.out.println(formatter.format(LocalTime.of(15, 30))); // Time: at 03:30:00 P 

String format = "dd/MM/yyyy \'at\' hh:mm:ss a z"; 
DateTimeFormatter formatter = // use same code above, but with the modified regex split 
ZonedDateTime z = ZonedDateTime.of(2017, 5, 1, 10, 20, 30, 0, ZoneId.of("America/Sao_Paulo")); 
System.out.println(formatter.format(z)); // 01/05/2017 at 10:20:30 A BRT 
関連する問題