如何在Java中获取日期的日期模式


public void parsedate(String date) {
DateTimeFormatter formatter = null;
formatter = new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ofPattern("yyyyMMdd"))
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
.appendOptional(DateTimeFormatter.ofPattern("MM/dd/yyyy")).toFormatter();
TemporalAccessor parse = formatter.parse(date);
System.out.println("original" + date);

return LocalDateTime.parse(date, formatter);
}
String[] strDates = new String[]{
"20180429",
"2018-04-29",
"04/29/2018",
"01/20/1999",
"1899-12-25",
"2020-02-29", // leap year future
"00010101",
"19160229" // leap year past
};
for(String date: strDates) {
parsedate(date);
}

我正在分析具有多个日期模式的日期。我将把日期字符串传递给parsedate方法。我的日期字符串已解析。但我想得到被解析的日期模式。

示例:

输入日期:";2018-04-29";过程:parsedate("2018-04-29"(输出:日期解析成功

我的期望是得到";yyyy-MM-dd";对于输入日期:";2018-04-29";。如何获取?

我同意Andreas在评论中的观点:品尝日期字符串以确定其格式非常简单。

public static String getPattern(String dateString) {
if (dateString.length() == 8) { // compact format
return "uuuuMMdd";
} else if (dateString.charAt(2) == '/') {
return "MM/dd/uuuu";
} else {
return "uuuu-MM-dd";
}
}

用你的问题中的样本字符串试试:

String[] strDates = new String[]{
"20180429",
"2018-04-29",
"04/29/2018",
"01/20/1999",
"1899-12-25",
"2020-02-29", // leap year this year
"00010101",
"19160229" // leap year past
};
for(String date: strDates) {
String pattern = getPattern(date);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
LocalDate parsedDate = LocalDate.parse(date, formatter);
System.out.format("%-10s pattern: %-10s parsed: %s%n", date, pattern, parsedDate);
}

输出为:

20180429   pattern: uuuuMMdd   parsed: 2018-04-29
2018-04-29 pattern: uuuu-MM-dd parsed: 2018-04-29
04/29/2018 pattern: MM/dd/uuuu parsed: 2018-04-29
01/20/1999 pattern: MM/dd/uuuu parsed: 1999-01-20
1899-12-25 pattern: uuuu-MM-dd parsed: 1899-12-25
2020-02-29 pattern: uuuu-MM-dd parsed: 2020-02-29
00010101   pattern: uuuuMMdd   parsed: 0001-01-01
19160229   pattern: uuuuMMdd   parsed: 1916-02-29

如果您更喜欢动态、自动化和可扩展的解决方案:

private static final String[] formatPatterns = { "uuuuMMdd", "uuuu-MM-dd", "MM/dd/uuuu" };
public static String getPattern(String dateString) {
for (String pattern : formatPatterns) {
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
LocalDate.parse(dateString, formatter);
// If we ended up here, using the pattern was successful
return pattern;
} catch (DateTimeParseException dtpe) {
// Do nothing, try next pattern
}
}
throw new IllegalArgumentException("We don’t know the format pattern string for " + dateString);
}

在查看了文档之后,似乎看不出哪种可选格式成功了。因此,简单的方法是构建一个格式化程序集合进行尝试,并按顺序使用它们,直到成功为止。然而,这是丑陋的:您使用异常进行流量控制

LocalDateTime time = null;
DateTimeFormatter goodFormatter = null;
for (DateTimeFormatter formatter : formats) {
try {
time = LocalDateTime.parse(date, formatter);
goodFormatter = formatter;
break;
} catch (DateTimeParseException dtpe) {
// not really exceptional - bad coding practice
}
}
// if goodFormatter != null, there you have it

关于SO的一个现有问题处理了这个问题。我建议的答案与其中一个答案一致。

一个更干净的选择可能是将您的格式用作正则表达式(仅检查可能的候选者(和实际日期格式(仅解析好的候选者(。这是以可读性为代价的,并且在解析不明确的格式时仍然会抛出异常,因为正则表达式代码的格式非常简单:

enum FormatCandidate {
YMD("yyyyMMdd"),
YMD_DASHED("yyyy-MM-dd"),
MDY_SLASHED("MM/dd/yyyy");
private final Pattern pattern;
public final DateTimeFormatter formatter;  // immutable & thread safe
FormatCandidate(String format) {
// THIS ONLY WORKS FOR SIMPLE EXAMPLES; modify for more complex ones!
this.pattern = Pattern.compile(format
.replaceAll("[-/]", "\")  // preserved characters
.replaceAll("[yMd]","\d")   // digits
));
this.formatter = new DateTimeFormatterBuilder()
.appendPattern(format).toFormatter();
}
// this should really be available in the DateTimeFormatter class
public boolean canParse(String date) {
return pattern.matcher(date).matches();
}
}

初始代码现在可以写成:

DateTimeFormatter goodFormatter = null;
for (FormatCandidate candidate : FormatCandidate.values()) {
if (candidate.canParse(date)) {
goodFormatter = candidate.format;
break;
}
}
LocalDateTime time = null;   
try {
time = LocalDateTime.(date, candidate.formatter);
} catch (DateTimeParseException dtpe) {
// now we can complain, saying that date does not match this particular
// expected output
}

在进一步复杂化之前,我可能只会将丑陋的异常作为控制流(第一个代码片段(,作为重新实现时间解析库的一种较小的邪恶。

免责声明:上述代码未经测试,可能无法按预期编译和/或执行

FTA,我是其中的作者(https://github.com/tsegall/fta)旨在解决这个问题(以及其他问题(。它目前解析数千种格式,而不是通过预定义的集合来完成,因此通常运行速度极快。这里有一个例子,第一行大约是提供的样本集,第二行有一组额外的样本:

public static void main(final String[] args) {
String[] strDates = {
"20180429", "2018-04-29", "04/29/2018", "01/20/1999", "1899-12-25", "2020-02-29", "20010101", "19160229",
"2018.04.29", "2018.29.04", "04.29.2018", "29.04.2018", "04.2018.29", "29.2018.04", "2020/2/29",
};

final DateTimeParser dtp = new DateTimeParser();
for(String date: strDates) {
String pattern = dtp.determineFormatString(date);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
LocalDate parsedDate = LocalDate.parse(date, formatter);
System.out.format("%-10s pattern: %-10s parsed: %s%n", date, pattern, parsedDate);
}
}

它将给出以下输出:

20180429   pattern: yyyyMMdd   parsed: 2018-04-29
2018-04-29 pattern: yyyy-MM-dd parsed: 2018-04-29
04/29/2018 pattern: MM/dd/yyyy parsed: 2018-04-29
01/20/1999 pattern: MM/dd/yyyy parsed: 1999-01-20
1899-12-25 pattern: yyyy-MM-dd parsed: 1899-12-25
2020-02-29 pattern: yyyy-MM-dd parsed: 2020-02-29
20010101   pattern: yyyyMMdd   parsed: 2001-01-01
19160229   pattern: yyyyMMdd   parsed: 1916-02-29
2018.04.29 pattern: yyyy.MM.dd parsed: 2018-04-29
2018.29.04 pattern: yyyy.dd.MM parsed: 2018-04-29
04.29.2018 pattern: MM.dd.yyyy parsed: 2018-04-29
29.04.2018 pattern: dd.MM.yyyy parsed: 2018-04-29
04.2018.29 pattern: MM.yyyy.dd parsed: 2018-04-29
29.2018.04 pattern: dd.yyyy.MM parsed: 2018-04-29
2020/2/29  pattern: yyyy/M/dd  parsed: 2020-02-29

相关内容

  • 没有找到相关文章

最新更新