私は要素に提供された日付書式文字列を削除する - たとえば、変換用フォーマット「DD / MM / YYYY」「MM / YYYY」に任意の非M / Yの要素を取り除くことによって。
私は何をしようとしていることはロケールのために提供、既存の日/月/年の形式に基づいて、ローカライズされた月/年の形式を作成することです。
私は正規表現を使用して、これをやったが、解決策は、私が期待するよりも長いようです。
以下の例は次のとおりです。
public static void main(final String[] args) {
System.out.println(filterDateFormat("dd/MM/yyyy HH:mm:ss", 'M', 'y'));
System.out.println(filterDateFormat("MM/yyyy/dd", 'M', 'y'));
System.out.println(filterDateFormat("yyyy-MMM-dd", 'M', 'y'));
}
/**
* Removes {@code charsToRetain} from {@code format}, including any redundant
* separators.
*/
private static String filterDateFormat(final String format, final char...charsToRetain) {
// Match e.g. "ddd-"
final Pattern pattern = Pattern.compile("[" + new String(charsToRetain) + "]+\\p{Punct}?");
final Matcher matcher = pattern.matcher(format);
final StringBuilder builder = new StringBuilder();
while (matcher.find()) {
// Append each match
builder.append(matcher.group());
}
// If the last match is "mmm-", remove the trailing punctuation symbol
return builder.toString().replaceFirst("\\p{Punct}$", "");
}
のは、以下の日付形式の文字列のためのソリューションを試してみましょう:
String[] formatStrings = { "dd/MM/yyyy HH:mm:ss",
"MM/yyyy/dd",
"yyyy-MMM-dd",
"MM/yy - yy/dd",
"yyabbadabbadooMM" };
以下は、次に、一致する文字列を解析し、一致の最初のグループを表示します。
Pattern p = Pattern.compile(REGEX);
for(String formatStr : formatStrings) {
Matcher m = p.matcher(formatStr);
if(m.matches()) {
System.out.println(m.group(1));
}
else {
System.out.println("Didn't match!");
}
}
さて、私が試した二つの別々の正規表現があります。最初:
final String REGEX = "(?:[^My]*)([My]+[^\\w]*[My]+)(?:[^My]*)";
プログラムの出力を持ちます:
MM / YYYY
MM / YYYYの
YYYY-MMMは
一致しませんでした!
一致しませんでした!
第二:
final String REGEX = "(?:[^My]*)((?:[My]+[^\\w]*)+[My]+)(?:[^My]*)";
プログラムの出力を持ちます:
MM / YYYY
MM / YYYYの
YYYY-MMM
MM / yyyyは
一致しませんでした!
それでは、最初の正規表現が実際に一致するか見てみましょう:
(?:[^My]*)([My]+[^\\w]*[My]+)(?:[^My]*) First regex =
(?:[^My]*) Any amount of non-Ms and non-ys (non-capturing)
([My]+ followed by one or more Ms and ys
[^\\w]* optionally separated by non-word characters
(implying they are also not Ms or ys)
[My]+) followed by one or more Ms and ys
(?:[^My]*) finished by any number of non-Ms and non-ys
(non-capturing)
これが意味することは、彼らは2つのM-または-yの領域の1つの文字を持っているので、MM-DDまたはYY-DDのようなものは、同様に一致することを注意しなければならないが、少なくとも2 M / YSは、正規表現と一致する必要があるということです長いです。あなただけのような、あなたの日付フォーマット文字列に健全性チェックを保つことによって、ここでトラブルに避けることができます。
if(formatStr.contains('y') && formatStr.contains('M') && m.matches())
{
String yMString = m.group(1);
... // other logic
}
第二の正規表現については、ここでそれが何を意味するのかです:
(?:[^My]*)((?:[My]+[^\\w]*)+[My]+)(?:[^My]*) Second regex =
(?:[^My]*) Any amount of non-Ms and non-ys
(non-capturing)
( ) followed by
(?:[My]+ )+[My]+ at least two text segments consisting of
one or more Ms or ys, where each segment is
[^\\w]* optionally separated by non-word characters
(?:[^My]*) finished by any number of non-Ms and non-ys
(non-capturing)
この正規表現は、文字列のやや広いシリーズを一致しますが、それはまだMsとYSとの間の分離は非言葉(であることが必要[^a-zA-Z_0-9]
)。また、この正規表現はまだ「YY」、「MM」、または「YYY」のような類似文字列、「YYYY」に一致することに注意してください...、前の通常のために説明したように、健全性チェックを有することが有用であろうように、表現。
また、ここで1は、単一の日付書式文字列を操作するために、上記を使用する方法の簡単な例を示します。
LocalDateTime date = LocalDateTime.now();
String dateFormatString = "dd/MM/yyyy H:m:s";
System.out.println("Old Format: \"" + dateFormatString + "\" = " +
date.format(DateTimeFormatter.ofPattern(dateFormatString)));
Pattern p = Pattern.compile("(?:[^My]*)([My]+[^\\w]*[My]+)(?:[^My]*)");
Matcher m = p.matcher(dateFormatString);
if(dateFormatString.contains("y") && dateFormatString.contains("M") && m.matches())
{
dateFormatString = m.group(1);
System.out.println("New Format: \"" + dateFormatString + "\" = " +
date.format(DateTimeFormatter.ofPattern(dateFormatString)));
}
else
{
throw new IllegalArgumentException("Couldn't shorten date format string!");
}
出力:
旧フォーマット: "DD / MM / YYYYのH:M:S" = 14/08/2019夜四時55分45秒
の新フォーマット: "MM / YYYY" = 08/2019