我正在开发一个 REST API,它支持日期作为查询参数。由于它是查询参数,因此它将是字符串。现在可以在 QueryParams 中以以下格式发送日期:
yyyy-mm-dd[(T| )HH:MM:SS[.fff]][(+|-)NNNN]
这意味着以下是有效日期:
2017-05-05 00:00:00.000+0000
2017-05-05 00:00:00.000
2017-05-05T00:00:00
2017-05-05+0000
2017-05-05
现在解析我正在使用的所有这些不同的日期时间Java8 datetime
API。代码如下所示:
DateTimeFormatter formatter = new DateTimeFormatterBuilder().parseCaseInsensitive()
.append(DateTimeFormatter.ofPattern("yyyy-MM-dd[[ ][['T'][ ]HH:mm:ss[.SSS]][Z]"))
.toFormatter();
LocalDateTime localDateTime = null;
LocalDate localDate = null;
ZoneId zoneId = ZoneId.of(ZoneOffset.UTC.getId());
Date date = null;
try {
localDateTime = LocalDateTime.parse(datetime, formatter);
date = Date.from(localDateTime.atZone(zoneId).toInstant());
} catch (Exception exception) {
System.out.println("Inside Excpetion");
localDate = LocalDate.parse(datetime, formatter);
date = Date.from(localDate.atStartOfDay(zoneId).toInstant());
}
从我使用的代码可以看出DateTimeFormatter
并附加一个模式。现在我首先尝试将日期解析为LocalDateTime
in the try-block
如果它抛出这样的情况的异常2017-05-05
因为没有时间过去,我正在使用LocalDate
in the catch block
.
上述方法为我提供了我正在寻找的解决方案,但我的问题是,这是处理作为字符串发送的日期的标准方法吗?我的方法是否符合这些标准?
另外,如果可能的话,我可以解析不同类型的日期(如上面的有效日期所示)的其他方法是什么,除了一些其他简单的解决方案,例如使用数组列表并放置所有可能的格式,然后使用 for 循环尝试解析日期?
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
// time is optional
.optionalStart()
.parseCaseInsensitive()
.appendPattern("[ ]['T']")
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.optionalEnd()
// offset is optional
.appendPattern("[xx]")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter();
for (String queryParam : new String[] {
"2017-05-05 00:00:00.000+0000",
"2017-05-05 00:00:00.000",
"2017-05-05T00:00:00",
"2017-05-05+0000",
"2017-05-05",
"2017-05-05T11:20:30.643+0000",
"2017-05-05 16:25:09.897+0000",
"2017-05-05 22:13:55.996",
"2017-05-05t02:24:01"
}) {
Instant inst = OffsetDateTime.parse(queryParam, formatter).toInstant();
System.out.println(inst);
}
该片段的输出是:
2017-05-05T00:00:00Z
2017-05-05T00:00:00Z
2017-05-05T00:00:00Z
2017-05-05T00:00:00Z
2017-05-05T00:00:00Z
2017-05-05T11:20:30.643Z
2017-05-05T16:25:09.897Z
2017-05-05T22:13:55.996Z
2017-05-05T02:24:01Z
我使用的技巧包括:
- 可选部件可以包含在任一部件中
optionalStart
/optionalEnd
or in []
在一个模式中。我两种方式都用,我觉得每种方式都更容易阅读,你可能更喜欢不同的方式。
- 已经有针对日期和时间的预定义格式化程序,因此我重复使用它们。我特别利用了这样一个事实:
DateTimeFormatter.ISO_LOCAL_TIME
已经处理可选的秒和秒的小数部分。
- 用于解析成
OffsetDateTime
为了工作,我们需要为查询参数中可能缺少的部分提供默认值。parseDefaulting
做这个。
在您的代码中,您正在转换为Date
. The java.util.Date
类早已过时并且存在许多设计问题,因此如果可以的话请避免使用它。Instant
会做得很好。如果您确实需要Date
对于您现在无法更改或不想更改的旧版 API,请按照问题中的相同方式进行转换。
编辑:现在默认HOUR_OF_DAY
, not MILLI_OF_DAY
。当仅缺少毫秒时,后者会引起冲突,但格式化程序似乎对缺少时间的默认小时感到满意。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)