質問
フランス語ロケールの日付を表す文字列を持っています:09-oct-08:
その文字列を解析する必要があるので、このSimpleDateFormatを思いつきました:
String format2 = "dd-MMM-yy";
しかし、月の部分に問題があり、それは終了ドットで予想されるようです:
df2.format(new Date());
私を与えてくれます:
28-oct.-09
SimpleDateFormatに理解させるための最良の方法は何ですか(" 09-oct-08")?
完全なコード:
String format2 = "dd-MMM-yy";
DateFormat df2 = new SimpleDateFormat(format2,Locale.FRENCH);
date = df2.parse("09-oct-08");
これにより、java.text.ParseException:Unparseable date:" 09-oct-08"が得られます。
そして、ログに記録しようとした場合:
df2.format(new Date());
取得:28-oct.-09
解決
これは動作しているようです:
DateFormatSymbols dfsFr = new DateFormatSymbols(Locale.FRENCH);
String[] oldMonths = dfsFr.getShortMonths();
String[] newMonths = new String[oldMonths.length];
for (int i = 0, len = oldMonths.length; i < len; ++ i) {
String oldMonth = oldMonths[i];
if (oldMonth.endsWith(".")) {
newMonths[i] = oldMonth.substring(0, oldMonths[i].length() - 1);
} else {
newMonths[i] = oldMonth;
}
}
dfsFr.setShortMonths(newMonths);
DateFormat dfFr = new SimpleDateFormat(
"dd-MMM-yy", dfsFr);
// English date parser for creating some test data.
DateFormat dfEn = new SimpleDateFormat(
"dd-MMM-yy", Locale.ENGLISH);
System.out.println(dfFr.format(dfEn.parse("10-Oct-09")));
System.out.println(dfFr.format(dfEn.parse("10-May-09")));
System.out.println(dfFr.format(dfEn.parse("10-Feb-09")));
編集:聖影が私を打ち負かしたように見えます。
他のヒント
単に&quot;。&quot;を削除できます:
df2.format(new Date()).replaceAll("\\.", ""));
編集、レモンの回答に関して:
フランス語のロケールを使用する場合、フォーマットに問題があるようです。したがって、説明したように。
の削除を使用することをお勧めします。
実際、次のコード:
String format2 = "dd-MMM-yy";
Date date = Calendar.getInstance().getTime();
SimpleDateFormat sdf = new SimpleDateFormat(format2, Locale.FRENCH);
System.out.println(sdf.format(date));
sdf = new SimpleDateFormat(format2, Locale.ENGLISH);
System.out.println(sdf.format(date));
次の出力を表示します。
28-oct.-09
28-Oct-09
もう一度編集
わかりました、今あなたの問題を受け取りました。
最初に文字列を処理せずにこの問題を解決する方法はわかりません。元の文字列の月を包括的な月に置き換えるという考え方です:
String[] givenMonths = { "jan", "fév", "mars", "avr.", "mai", "juin", "juil", "août", "sept", "oct", "nov", "déc" };
String[] realMonths = { "janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc." };
String original = "09-oct-08";
for (int i = 0; i < givenMonths.length; i++) {
original = original.replaceAll(givenMonths[i], realMonths[i]);
}
String format2 = "dd-MMM-yy";
DateFormat df2 = new SimpleDateFormat(format2, Locale.FRENCH);
Date date = df2.parse(original);
System.out.println("--> " + date);
同意しますが、これはひどいですが、 SimpleDateFormat
および Date
クラスに使用する場合、他の解決策は見当たりません。
別の解決策は、元のJDKの代わりに実際の日時ライブラリを使用することです"nofollow noreferrer">ジョーダ時間。
String format2 = "dd-MMM-yy";
Date date = Calendar.getInstance().getTime();
SimpleDateFormat sdf = new SimpleDateFormat(format2);
System.out.println(sdf.format(date));
出力 28-Oct-09
ドットが表示されません。プリントを再確認してみましたか?たぶん、誤って。
を MMM
の横に置いたのでしょうか?
&quot; 09-oct-08&quot;
が一致しないため、 java.text.ParseException:Unparseable date:&quot; 09-oct-08&quot;
が発生しています。 Locale.FRENCH
のフォーマットは、デフォルトのロケール(米国が考える)を使用するか、 oct
。
を追加します。 OK、それから「力ずく」を試して:)
DateFormatSymbols dfs = new DateFormatSymbols(Locale.FRENCH);
String[] months = new String[13]
<fill with correct month names or just replace these month, that are not fully correct>
dfs.setMonths(months);
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yy", dfs);
Date nweDate = sdf.parse("09-fév-08");
java.time
java.time フレームワークが役立つかどうか見てみましょう。
java.timeについて
java.time Java 8以降に組み込まれたフレームワークは、面倒な古いjava.util.Date/.Calendarクラスに取って代わります。新しいクラスは、非常に成功した Joda-Time フレームワークにインスパイアされており、後継となるものとして、概念的には再構築されました。 JSR 310 で定義されています。 ThreeTen-Extra プロジェクトによって拡張されました。 チュートリアルを参照してください。
LocalDate
古いクラスとは異なり、java.timeはを提供します LocalDate
クラスは、時刻もタイムゾーンもない日付のみの値を表します。
フランス語の略語
java.timeのフォーマッタが、 en Fran&#231; ais の短縮月名に期待するものを見てみましょう。
Month
列挙型で月のリストを取得します。この列挙は、 getDisplayName <月のローカライズされた名前を生成するための/ code>
メソッド。このコードは、メソッドがjava.timeフォーマッタと同じ出力を生成することを示しています。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "dd-MMM-yyyy" ).withLocale ( Locale.FRENCH );
for ( Month month : Month.values () ) {
LocalDate localDate = LocalDate.of ( 2015 , month.getValue () , 1 );
String output = formatter.format ( localDate );
String displayName = month.getDisplayName ( TextStyle.SHORT , Locale.FRENCH );
System.out.println ( "output: " + output + " | displayName: " + displayName );// System.out.println ( "input: " + input + " → " + localDate + " → " + output );
}
output: 01-janv.-2015 | displayName: janv.
output: 01-févr.-2015 | displayName: févr.
output: 01-mars-2015 | displayName: mars
output: 01-avr.-2015 | displayName: avr.
output: 01-mai-2015 | displayName: mai
output: 01-juin-2015 | displayName: juin
output: 01-juil.-2015 | displayName: juil.
output: 01-août-2015 | displayName: août
output: 01-sept.-2015 | displayName: sept.
output: 01-oct.-2015 | displayName: oct.
output: 01-nov.-2015 | displayName: nov.
output: 01-déc.-2015 | displayName: déc.
3文字と4文字のスペルが混在しています。長い名前は、4文字とピリオドに短縮されます(フルストップ )。 4か月には、略語なしで使用できるほど短い名前があります: mars
、 mai
、 juin
、 ao&#251; t
。
したがって、他の回答で説明したように、簡単な解決策はありません。
データソースの修正
最初の提案は、データソースを修正することです。その情報源は、明らかに短縮のための適切なフランスの規則に従わないようです。 Yale は、Java 8&#8217;のフランス語の理解に同意しています。ところで、データソースを修正する場合は、4桁の年を2として使用することを強くお勧めします。これにより、混乱とあいまいさがなくなることはありません。
入力を修正
もちろん、ソースはあなたの制御/影響から外れているかもしれません。その場合、他のアンサーと同様に、巧妙さを試みるのではなく、ブルートフォースリプレースメントを行う必要があります。一方、入力の唯一の問題がピリオドの欠落(完全な停止)である場合、不適切な値をハードコーディングするのではなく、 Month
列挙を使用してソフトコーディングできます。
最初の解析を試みます。 DateTimeParseException
のトラップ、修正を試みる前。例外がスローされた場合は、入力を修正してください。
入力を修正するには、enumインスタンスの可能なセットをループすることにより、年の各月を試行します。各月について、その短縮名を取得します。不適切な着信値と思われるものと一致するように、その省略形からピリオド(完全停止)を取り除きます。それが実際に入力に一致するかどうかをテストします。そうでない場合は、来月に行きます。
一致する場合は、ロケールのルール(この場合はフランスのルール)の入力が適切に短縮されるように入力を修正します。次に、固定入力を解析します。最初に最初の試行を行ったため、これは2回目の解析試行になります。この2回目の試行が失敗した場合、何かが
同じ問題(フランス語と余分なドット)がありました。この問題を解決する正しい方法は、フランス語ロケールをグローバルに次のように上書きすることだと思います:
import moment from 'moment';
moment.locale('fr', { monthsShort: 'janv_févr_mars_avr_mai_juin_juil_août_sept_oct_nov_déc'.split('_') });
元の monthsShort
フランス語オブジェクトには、次のようなドットがあります
janv._f&#233; vr._mars_avr ._...
なので、削除するだけです。
ここにドキュメントへのリンクがあり、上書きできる内容を確認できます。
単に上書きする場合は、完全なロケールオブジェクトを渡す必要がないことに注意してください。例: monthsShort
。