_Java.time.format.DateTimeFormatter
_ が期待どおりに解析できないことに気づきました。下記参照:
_import Java.time.LocalDate;
import Java.time.format.DateTimeFormatter;
public class Play {
public static void tryParse(String d,String f) {
try {
LocalDate.parse(d, DateTimeFormatter.ofPattern(f));
System.out.println("Pass");
} catch (Exception x) {System.out.println("Fail");}
}
public static void main(String[] args) {
tryParse("26-may-2015","dd-L-yyyy");
tryParse("26-May-2015","dd-L-yyyy");
tryParse("26-may-2015","dd-LLL-yyyy");
tryParse("26-May-2015","dd-LLL-yyyy");
tryParse("26-may-2015","dd-M-yyyy");
tryParse("26-May-2015","dd-M-yyyy");
tryParse("26-may-2015","dd-MMM-yyyy");
tryParse("26-May-2015","dd-MMM-yyyy");
}
}
_
tryParse("26-May-2015","dd-MMM-yyyy");
を使用した最後の試行のみが「成功」します。ドキュメントのとおり、LLL
はテキスト形式を解析できるはずです。大文字の「M」と小文字の「m」の微妙な違いにも注意してください。
デフォルトではOracle DBによってフォーマットされた文字列をデフォルトで解析できないため、これは本当に煩わしいです
_SELECT TO_DATE(SYSDATE,'DD-MON-YYYY') AS dt FROM DUAL;
_
同様に、次のプログラムの場合:
_import Java.time.LocalDate;
import Java.time.format.DateTimeFormatter;
public class Play {
public static void output(String f) {
LocalDate d = LocalDate.now();
Locale l = Locale.US;
// Locale l = Locale.forLanguageTag("ru");
System.out.println(d.format(DateTimeFormatter.ofPattern(f,l)));
}
public static void main(String[] args) {
output("dd-L-yyyy");
output("dd-LLL-yyyy");
output("dd-M-yyyy");
output("dd-MMM-yyyy");
}
}
_
私は以下の出力を得ます:
_28-5-2015
28-5-2015
28-5-2015
28-May-2015
_
明らかにL
書式指定子はテキストを何も扱わず、私には数値のように見えます...
ただし、ロケールをLocale.forLanguageTag("ru")
に変更すると、次の出力が得られます。
_28-5-2015
28-Май-2015
28-5-2015
28-мая-2015
_
本当に面白いですよね。
私が持っている質問は:
L
パターン指定子の使い方を誤解していますか?.私が「重要」だと思ったドキュメントの一部を引用します:
Text:テキストスタイルは、使用されるパターン文字の数に基づいて決定されます。パターン文字が4文字未満の場合は、短い形式を使用します。正確に4つのパターン文字は完全な形式を使用します。正確に5つのパターン文字が狭いフォームを使用します。 パターン文字「L」、「c」、および「q」は、スタンドアロンスタイルのテキストスタイルを指定します。
Number:文字数が1の場合、値は最小桁数でパディングなしで出力されます。それ以外の場合、桁数は出力フィールドの幅として使用され、必要に応じて値にゼロが埋め込まれます。次のパターン文字は文字数に制約があります。 「c」と「F」の1文字のみ指定できます。 「d」「H」「h」「K」「k」「m」「s」の2文字まで指定できます。 「D」は3文字まで指定できます。
数値/テキスト:パターン文字の数が3以上の場合、上記のテキストルールを使用します 。それ以外の場合は、上記の数値ルールを使用します。
[〜#〜]更新[〜#〜]
Oracleに2つの提出を行いました。
「L」は、日付で使用されている方法とは異なり、月自体に別のWordを使用する言語を意味していると思います。例えば:
Locale russian = Locale.forLanguageTag("ru");
asList("MMMM", "LLLL").forEach(ptrn ->
System.out.println(ptrn + ": " + ofPattern(ptrn, russian).format(Month.MARCH))
);
出力:
MMMM: марта
LLLL: Март
日付の解析時に「M」の代わりに「L」を使用する理由はありません。
次のことを試して、スタンドアロンの月の名前のフォーマットをサポートしているロケールを確認しました。
Arrays.stream(Locale.getAvailableLocales())
.collect(partitioningBy(
loc -> "3".equals(Month.MARCH.getDisplayName(FULL_STANDALONE, loc)),
mapping(Locale::getDisplayLanguage, toCollection(TreeSet::new))
)).entrySet().forEach(System.out::println);
以下の言語は、「LLLL」からロケール固有のスタンドアロンの月名を取得します。
カタロニア語、中国語、クロアチア語、チェコ語、フィンランド語、ギリシャ語、ハンガリー語、イタリア語、リトアニア語、ノルウェー語、ポーランド語、ルーマニア語、ロシア語、スロバキア語、トルコ語、ウクライナ語
他のすべての言語は、3月のスタンドアロン名として「3」を取得します。
Javadocsによると:
パターン文字「L」、「c」、および「q」は、スタンドアロンスタイルのテキストスタイルを指定します。
しかし、「スタンドアロン」のフォームがどうあるべきかについては、あまりわかりませんでした。コードを見ると、 'L'を使用するとTextStyle.SHORT_STANDALONE
が選択され、そのjavadocに従っていることがわかります。
スタンドアロンで使用するための短いテキスト。通常は省略形。たとえば、曜日の月曜日は "Mon"を出力します。
しかし、それはそれが機能するように見える方法ではありません。 3文字でも、このコードから数値出力が得られます。
DateTimeFormatter pattern = DateTimeFormatter.ofPattern ("dd-LLL-yyyy");
System.out.println (pattern.format (LocalDate.now ()));
編集
さらに調査した結果、これらのコードの「スタンドアロン」バージョンは、おそらくDateTimeFormatterBuilder
を使用して、ロケールに依存しない独自のデータをロードしたい場合のものであるように思われます。そのため、デフォルトでは、DateTimeFormatter
にはTextStyle.SHORT_STANDALONE
のエントリが読み込まれていません。
他の回答はパターン文字L
と日付の解析に関する優れた情報を提供しますが、問題を完全に回避する必要があることを付け加えておきます。データベースから日付(および時刻)を文字列として取得しないでください。代わりに、適切な日時オブジェクトを使用してください。
String sql = "select sysdate as dt from dual;"
PreparedStatement stmt = yourDatabaseConnection.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
LocalDateTime dateTime = rs.getObject("dt", LocalDateTime.class);
// do something with dateTime
}
(Oracleデータベースが手元にないため、テストされていません。タイプミスはご容赦ください。)