我需要将不同的时间格式解析为BASIC_ISO_DATE
。现在,有4种类型的日期格式:
2016-10-01
(ISO_LOCAL_DATE)2016T
201610T
2016-02-07T22:03:39.937Z
(ISO 8601)需要解析为20161001
并打印出来,默认日期为01
,默认月份为Jan
。例子:
2016T
- > 20160101
201610T
- > 20161001
如何使用DateTimeFormatter
来实现此目标?
答案 0 :(得分:3)
为了补充@Flown's answer(完全适用于BTW),您还可以使用可选模式(由[]
分隔):
DateTimeFormatter parser = new DateTimeFormatterBuilder()
// optional ISO8601 date/time and offset
.appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// optional yyyy-MM-dd or yyyyT or yyyyMMT
.appendPattern("[yyyy-MM-dd][yyyy'T'][yyyyMM'T']")
// default day is 1
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1L)
// default month is January
.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1L)
// create formatter
.toFormatter();
这种方式完全相同。您可以选择哪一个更清晰或更容易维护。如果有批次不同的模式,使用[]
可能最终会让人更加困惑,IMO。
请注意,我使用的是ISO_OFFSET_DATE_TIME
而不是ISO_ZONED_DATE_TIME
。唯一的区别是ISO_ZONED_DATE_TIME
最后也接受时区名称(如[Europe/London]
),而ISO_OFFSET_DATE_TIME
则不然。 Check the javadoc了解更多信息。
答案 1 :(得分:2)
您可以构建自己的DateTimeFormatter
。
DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ISO_ZONED_DATE_TIME)
.appendOptional(DateTimeFormatter.ISO_LOCAL_DATE)
.appendOptional(new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4)
.optionalStart()
.appendValue(ChronoField.MONTH_OF_YEAR)
.optionalEnd()
.appendLiteral('T')
.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1L)
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1L)
.toFormatter())
.toFormatter();
String[] strings = {"2016-10-01", "2016T", "201610T", "2016-02-07T22:03:39.937Z"};
for (String s : strings) {
System.out.println(LocalDate.parse(s, dateTimeFormatter)
.format(DateTimeFormatter.BASIC_ISO_DATE));
}
答案 2 :(得分:1)
尝试这样的事情:
public LocalDate parse(String str) {
// Might want to add some checks here...
String text = (str.replaceAll("[\-T]", "") + "0101").substring(0, 8);
return LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyyMMdd"));
}
答案 3 :(得分:1)
如果您只想要一个DateTimeFormatter
,Flown’s answer经过深思熟虑,可以很好地添加更多可能的格式或以其他方式更改要求。
我认为一个简单的替代方案是你使用三个或四个DateTimeFormatter
个对象并依次尝试它们直到一个工作。
对于2016T
,您可以像在Flown的回答中一样使用parseDefaulting()
,也可以只解析Year
,然后使用.atDay(1)
。同样适用于201610T
:一个选项是解析为YearMonth
并使用其atDay()
。
我的解决方案可能不太优雅,但可能更清晰。