Java解析API返回的带时区JSON日期报错,无法筛选日期范围
问题解决:日期解析错误与数据筛选实现
错误原因
你用的DateTimeFormatter.ISO_LOCAL_DATE_TIME只能解析无时区标识的本地日期时间字符串(比如2024-03-20T09:12:53.304420),但API返回的published_at末尾带Z(代表UTC时区),属于带时区的ISO-8601格式,这个Formatter识别不了末尾的Z,所以报出“未解析文本”的错误。
解决方案
方案1:用支持时区的DateTimeFormatter
直接换成DateTimeFormatter.ISO_ZONED_DATE_TIME,它专门处理带时区的日期时间字符串:
DateTimeFormatter formatter = DateTimeFormatter.ISO_ZONED_DATE_TIME; ZonedDateTime zonedDateTime = ZonedDateTime.parse(publishedAtStr, formatter);
方案2:不用Formatter,直接解析
你的日期字符串完全符合ISO-8601带时区的标准格式,ZonedDateTime可以直接解析,不用手动指定Formatter:
ZonedDateTime zonedDateTime = ZonedDateTime.parse(publishedAtStr);
修改后的完整代码片段
try { HttpResponse<String> response = HttpClient.newHttpClient().send(request, BodyHandlers.ofString()); String responseBody = response.body(); ObjectMapper mapper = new ObjectMapper(); ArrayNode offersArray = mapper.createArrayNode(); JsonNode rootNode = mapper.readTree(responseBody); JsonNode offers = rootNode.path("offers"); LocalDate startDate = LocalDate.of(2022, 6, 1); LocalDate endDate = LocalDate.of(2024, 4, 1); for (JsonNode offer : offers) { String publishedAtStr = offer.path("published_at").asText(); // 直接解析带时区的日期字符串 ZonedDateTime zonedDateTime = ZonedDateTime.parse(publishedAtStr); LocalDate publishedAt = zonedDateTime.toLocalDate(); // 简化日期筛选逻辑 if (!publishedAt.isBefore(startDate) && !publishedAt.isAfter(endDate)) { ObjectNode offerNode = mapper.createObjectNode(); offerNode.put("title", offer.path("title").asText()); offerNode.put("description", offer.path("description").asText()); offerNode.put("location", offer.path("location").asText()); offerNode.put("requirements", offer.path("requirements").asText()); offerNode.put("published_at", publishedAtStr); offersArray.add(offerNode); } } } catch (Exception e) { e.printStackTrace(); }
额外提示
- 要是只需要日期部分,也可以用
OffsetDateTime.parse(publishedAtStr).toLocalDate(),效果和ZonedDateTime一致,开销更小。 - 筛选条件
!publishedAt.isBefore(startDate) && !publishedAt.isAfter(endDate)和你原来的逻辑等价,写法更简洁。
内容的提问来源于stack exchange,提问作者Ilze
相关产品推荐
相关产品推荐

