legacyアプリケーションにコードとテストケースがあり、次のように要約できます。
@Test
public void testParseDate() throws ParseException {
String toParse = "Mo Aug 18 11:25:26 MESZ +0200 2014";
String pattern = "EEE MMM dd HH:mm:ss z Z yyyy";
DateFormat dateFormatter = new SimpleDateFormat(pattern, Locale.GERMANY);
Date date = dateFormatter.parse(toParse);
//skipped assumptions
}
このテストは、Java 8以下に合格します。ただし、Java 10以上の場合、Java.text.ParseException: Unparseable date: "Mo Aug 18 11:25:26 MESZ +0200 2014"
になります。
レコードの場合:de_DE
に加えて、ロケールde_CH
、de_AT
、de_LU
の例外もスローされます。
日付のフォーマットが JDK 9で変更 ( JEP 252 )であったという事実を知っています。ただし、これは後方互換性を壊す破壊的な変更であると考えています。抜粋:
JDK 9では、Unicodeコンソーシアムの共通ロケールデータリポジトリ(CLDR)データがデフォルトのロケールデータとして有効になっているため、標準のロケールデータをそのまま使用できます。
JDK 8では、CLDRロケールデータはJREにバンドルされていますが、デフォルトでは有効になっていません。
日付、時刻、数値のフォーマットなど、ロケールに依存するサービスを使用するコードは、CLDRロケールデータで異なる結果を生成する場合があります。
曜日に.
を追加すると(Mo.
)、これを補正し、テストに合格します。ただし、これは古いデータ(XMLなどのシリアル形式)の実際のソリューションではありません。
これを確認すると stackoverflow post 、ドイツ語のロケールではこの動作が意図的であり、Java.locale.providers
をCOMPAT
モードで指定することで軽減できるようです。ただし、次の2つの理由から、システムプロパティの値に依存するという考えは好きではありません。
私の質問は:
Java.locale.providers
など)を書き換えたり変更したりすることなく、異なる環境(アプリケーションサーバー、スタンドアロンjar、...)?私はそれがニースのソリューションだとは言いませんが、それは方法のようです。
_ Map<Long, String> dayOfWeekTexts = Map.of(1L, "Mo", 2L, "Di",
3L, "Mi", 4L, "Do", 5L, "Fr", 6L, "Sa", 7L, "So");
Map<Long, String> monthTexts = Map.ofEntries(Map.entry(1L, "Jan"),
Map.entry(2L, "Feb"), Map.entry(3L, "Mär"), Map.entry(4L, "Apr"),
Map.entry(5L, "Mai"), Map.entry(6L, "Jun"), Map.entry(7L, "Jul"),
Map.entry(8L, "Aug"), Map.entry(9L, "Sep"), Map.entry(10L, "Okt"),
Map.entry(11L, "Nov"), Map.entry(12L, "Dez"));
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendText(ChronoField.DAY_OF_WEEK, dayOfWeekTexts)
.appendLiteral(' ')
.appendText(ChronoField.MONTH_OF_YEAR, monthTexts)
.appendPattern(" dd HH:mm:ss z Z yyyy")
.toFormatter(Locale.GERMANY);
String toParse = "Mo Aug 18 11:25:26 MESZ +0200 2014";
OffsetDateTime odt = OffsetDateTime.parse(toParse, formatter);
System.out.println(odt);
ZonedDateTime zdt = ZonedDateTime.parse(toParse, formatter);
System.out.println(zdt);
_
Oracle JDK 10.0.1で実行されている出力:
_2014-08-18T11:25:26+02:00
2014-08-18T11:25:26+02:00[Europe/Berlin]
_
この場合も、ニースのソリューションは存在しない可能性があります。
_Java.time
_、最新のJava日時APIを使用すると、フォーマットと解析の両方のフィールドに使用するテキストを指定できます。そこで、これを悪用して、曜日と月の両方で、古いCOMPATまたはJREロケールデータで使用されていたドットなしの省略形を指定します。必要なマップの作成にJava 9 _Map.of
_および_Map.ofEntries
_を使用しました。これがJava 8でも機能する場合、2つのマップにデータを入力する他の方法を見つける必要があります。そうすることを信頼しています。
旧式の_Java.util.Date
_が必要な場合(おそらくレガシーコードベースで)、次のように変換します。
_ Date date = Date.from(odt.toInstant());
System.out.println("As legacy Date: " + date);
_
私のタイムゾーンでの出力(ヨーロッパ/コペンハーゲン、おそらくおおよそあなたのものと一致):
_As legacy Date: Mon Aug 18 11:25:26 CEST 2014
_
それが私なら、この方法で進めることを検討すると思います。
System.setProperty("Java.locale.providers", "COMPAT,CLDR");
どの環境でも忘れないようにします。 COMPATロケールデータは1.0以降(少なくとも近いと思います)、そこにある多くのコードは(あなただけではなく)それに依存しています。名前はJava 9でJREからCOMPATに変更されました。私にとっては、これはかなり長い間データを保持する計画のように思えます。 アーリーアクセスドキュメント によれば、Java 11(次の「長期サポート」Javaバージョン)で引き続き使用でき、廃止の警告もありません。など。また、将来のJavaバージョンで削除された場合、アップグレードする前に問題に対処できるほど早く見つけることができるでしょう。SimpleDateFormat
は、BTWがスレッドセーフではない日付をフォーマットする古い方法です。 Java 8以降、Java.time
およびJava.time.format
と呼ばれる新しいパッケージがあり、これらを使用して日付を処理する必要があります。目的に合わせて、クラス DateTimeFormatter を使用する必要があります。
Java 8はFr Juni 15 00:20:21 MESZ +0900 2018でしたが、Fr。Juni 15 00:20:21 MESZ +0900 2018 EEEが含まれます。 IS COMPATIBILITY ISSUE。古いバージョンのコードが新しいバージョンで動作しないことは問題ではありません。(翻訳者に申し訳ありません)日付文字列があなたの場合、新しいバージョンのユーザーにはドットを追加する必要があります。ユーザーはJava 8を使用してソフトウェアを使用します。
サブストリング方式を使用することもソフトウェアを遅くすることができます。
String toParse = "Mo Aug 18 11:25:26 MESZ +0200 2014";
String str = toParse.substring(0, 2) + "." + toParse.substring(2);
String pattern = "EEE MMM dd HH:mm:ss z Z yyyy";
DateFormat dateFormatter = new SimpleDateFormat(pattern, Locale.GERMANY);
System.out.println(dateFormatter.format(System.currentTimeMillis()));
Date date = dateFormatter.parse(str);
悪い英語でごめんね。