在 Java Spring 引导中使用 DateTimeFormatter 时获取不受支持的字段:DayOfMonth
Getting Unsupported field: DayOfMonth while using DateTimeFormatter in Java Spring Boot
确切错误:java.time.temporal.UnsupportedTemporalTypeException:不支持的字段:DayOfMonth
下面是我创建的 HashMap,我们可以在其中看到仅存在 3 个月的数据。最终目标是 create/update 从当月开始,使用最近 12 个月的数据动态生成 MAP。
这 3 个月以外的任何月份的值为 0L。
Map<String, Long> expectedValues = new HashMap<>();
expectedValues.put("2021-06-01", 10L);
expectedValues.put("2021-07-01", 20L);
expectedValues.put("2021-08-01", 30L);
我已经编写了这个逻辑来检查和填充不存在的月份的 0L。但是在使用 DateTimeFormatter
时出现错误
YearMonth thisMonth = YearMonth.now();
for (int i = 0; i < 12; i++) {
// DateTimeFormatter monthYearFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter monthYearFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
String prevYearMonthStr = thisMonth.minusMonths(i).format(monthYearFormatter);
if (!expectedValues.containsKey(prevYearMonthStr)) {
expectedValues.put(prevYearMonthStr, 0L);
}
}
我们如何解决这个错误。
嗯,YearMonth
只有一个年份和一个月份字段。然后您尝试使用 ISO_LOCAL_DATE_TIME
格式化程序对其进行格式化,它期望 Temporal
(在您的情况下为 YearMonth
)支持日期字段。
那显然不行。
您可以使用 YearMonth
的 atDay
方法,该方法将 YearMonth
转换为具有指定日期的 LocalDate
。接下来,这个 LocalDate
可以使用预定义的 ISO_LOCAL_DATE
格式化程序进行格式化,它等同于具有模式字符串 uuuu-MM-dd
.
的格式化程序
YearMonth thisMonth = YearMonth.now();
DateTimeFormatter format = DateTimeFormatter.ISO_LOCAL_DATE;
for (int i = 0; i < 12; i++) {
String prev = thisMonth.minusMonths(i).atDay(1).format(format);
if (!expectedValues.containsKey(prev)) {
expectedValues.put(prev, 0L);
}
}
或使用Java 8个特征:
static Map<String, Long> transform(Map<String, Long> expectedValues) {
DateTimeFormatter format = DateTimeFormatter.ISO_LOCAL_DATE;
return Stream.iterate(YearMonth.now(), ym -> ym.minusMonths(1))
.limit(12)
.map(ym -> ym.atDay(1).format(format))
.map(str -> Map.entry(str, expectedValues.getOrDefault(str, 0L)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
这是这里发生的事情:
Stream::iterate
接受一个初始值,即当前月份,然后遍历过去的每个月。
limit
确保我们有 12 个值,否则我们将有一个无限流。
- 第一个
map
将 YearMonth
转换为带有月份第一天的 LocalDate
。然后使用模式 uuuu-MM-dd
. 对其进行格式化
- 第二个
map
创建一个 Map.Entry
,其中流元素作为键,值是来自 expectedValues
映射的值,或者 0L
如果是键不存在。当然,这两个 map
调用可以合并。
- 然后我们收集流中当前包含的这些
Map.Entry<String, Long>
个元素,到一个Map
.
确切错误:java.time.temporal.UnsupportedTemporalTypeException:不支持的字段:DayOfMonth
下面是我创建的 HashMap,我们可以在其中看到仅存在 3 个月的数据。最终目标是 create/update 从当月开始,使用最近 12 个月的数据动态生成 MAP。
这 3 个月以外的任何月份的值为 0L。
Map<String, Long> expectedValues = new HashMap<>();
expectedValues.put("2021-06-01", 10L);
expectedValues.put("2021-07-01", 20L);
expectedValues.put("2021-08-01", 30L);
我已经编写了这个逻辑来检查和填充不存在的月份的 0L。但是在使用 DateTimeFormatter
时出现错误YearMonth thisMonth = YearMonth.now();
for (int i = 0; i < 12; i++) {
// DateTimeFormatter monthYearFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter monthYearFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
String prevYearMonthStr = thisMonth.minusMonths(i).format(monthYearFormatter);
if (!expectedValues.containsKey(prevYearMonthStr)) {
expectedValues.put(prevYearMonthStr, 0L);
}
}
我们如何解决这个错误。
嗯,YearMonth
只有一个年份和一个月份字段。然后您尝试使用 ISO_LOCAL_DATE_TIME
格式化程序对其进行格式化,它期望 Temporal
(在您的情况下为 YearMonth
)支持日期字段。
那显然不行。
您可以使用 YearMonth
的 atDay
方法,该方法将 YearMonth
转换为具有指定日期的 LocalDate
。接下来,这个 LocalDate
可以使用预定义的 ISO_LOCAL_DATE
格式化程序进行格式化,它等同于具有模式字符串 uuuu-MM-dd
.
YearMonth thisMonth = YearMonth.now();
DateTimeFormatter format = DateTimeFormatter.ISO_LOCAL_DATE;
for (int i = 0; i < 12; i++) {
String prev = thisMonth.minusMonths(i).atDay(1).format(format);
if (!expectedValues.containsKey(prev)) {
expectedValues.put(prev, 0L);
}
}
或使用Java 8个特征:
static Map<String, Long> transform(Map<String, Long> expectedValues) {
DateTimeFormatter format = DateTimeFormatter.ISO_LOCAL_DATE;
return Stream.iterate(YearMonth.now(), ym -> ym.minusMonths(1))
.limit(12)
.map(ym -> ym.atDay(1).format(format))
.map(str -> Map.entry(str, expectedValues.getOrDefault(str, 0L)))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
这是这里发生的事情:
Stream::iterate
接受一个初始值,即当前月份,然后遍历过去的每个月。limit
确保我们有 12 个值,否则我们将有一个无限流。- 第一个
map
将YearMonth
转换为带有月份第一天的LocalDate
。然后使用模式uuuu-MM-dd
. 对其进行格式化
- 第二个
map
创建一个Map.Entry
,其中流元素作为键,值是来自expectedValues
映射的值,或者0L
如果是键不存在。当然,这两个map
调用可以合并。 - 然后我们收集流中当前包含的这些
Map.Entry<String, Long>
个元素,到一个Map
.