我们有一个图书馆,用户可以在其中传递多种格式的日期。它们遵循ISO,但有时会缩写。
因此,我们得到的内容类似于“ 19-3-12”和“ 2019-03-12T13:12:45.1234”,其中小数秒可以是1-7位数长。这是很多组合。
DateTimeFormatter.parseBest不起作用,因为它在本地日期不接受“ yy-m-d”。 The solutions here不起作用,因为它假设我们知道模式-我们不知道。
告诉人们让他们的字符串格式“正确”是行不通的,因为存在大量的现有数据(这些数据大多在XML和JSON文件中)。
我的问题是,如何解析这些各种模式中出现的字符串而不必尝试15种不同的显式模式?
甚至更好的是,是否有某种方法可以解析字符串,并且如果该字符串在任何日期[时间]都有意义,它将尝试一切可能并返回一个Temporal对象?
答案 0 :(得分:0)
尝试所有可能的格式要比仅尝试15种格式差。
您可以尝试将“规范化”为单一格式,但是您将要做这15种格式应该做的工作。
我认为最好的方法是@JB Nizet描述的方法,只尝试匹配字符串长度的模式。
public Date parse(String openFormat) {
String[] formats = {"YYY-MM-DD"};
switch(openFormat.length()) {
case 24: // 2019-03-12T13:12:45.1234
formats = new String[]{"YYY-MM-DDThh:mm:ssetcetc", }; // all the formats for length 24
break;
...
case 6: //YYY-MM-DD, DD-MM-YYYY
formats = new String[]{YYY-MM-DD", "DD-MM-YYYY", }; // all the formats for length 6
break;
}
Date myDate
// now try the reduced number of formats, possibly only 1 or 2
for( String format : formats) try {
myDate = date parse ( format ) etcetc
} catch (DateFormatException d) {
continue;
}
if (myDate == null){
throw InvalidDate
} else {
return myDate
}
}
答案 1 :(得分:0)
没有完整的规范,很难给出准确的建议。通常用于可变格式的技术包括:
DateTimeFormatterBuilder.parseDefaulting()
表示解析的字符串中可能不存在的部分。parseBest
。我假设y-M-d总是以此顺序出现(例如,从不M-d-y或d-M-y)。 19-3-12
与ISO 8601冲突,因为该标准要求(至少)4位数字的年份和2位数字的月份。两位数年份的挑战正在猜测世纪:这是1919年还是2019年,或者可能是2119年?
好消息:秒的存在与否以及小数位数的变化都是内置的,并且没有问题。
根据您告诉我们的内容,在我看来以下内容是一个不错的选择。
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("[uuuu][uu]-M-d")
.optionalStart()
.appendLiteral('T')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.optionalEnd()
.toFormatter();
TemporalAccessor dt = formatter.parseBest("19-3-12", LocalDateTime::from, LocalDate::from);
System.out.println(dt.getClass());
System.out.println(dt);
输出:
class java.time.LocalDate 2019-03-12
我认为它应该与您描述的各种格式兼容。让我们尝试另一个示例:
dt = formatter.parseBest( "2019-03-12T13:12:45.1234", LocalDateTime::from, LocalDate::from);
System.out.println(dt.getClass());
System.out.println(dt);
class java.time.LocalDateTime 2019-03-12T13:12:45.123400
要控制两位数年份的解释,您可以使用Firestore screenshot的重载变体之一。我建议您考虑在其上方进行范围检查。