java - Java 8 DateTimeFormatter,可选部分不带秒
问题描述
已经存在带有可选部分的 Java 8 DateTimeFormatter问题,但是当可选部分只有小时和分钟而没有秒时,它的答案将不起作用:
DateTimeFormatter patternWithOptional = new DateTimeFormatterBuilder()
.appendPattern("M/d/yyyy[ h:mm]")
.toFormatter();
TemporalAccessor tmp = patternWithOptional.parseBest("4/11/2020 1:20", LocalDateTime::from, LocalDate::from);
System.out.println(tmp);
System.out.println(tmp.getClass().getSimpleName());
// prints 2020-04-11, without time
// class is LocalDate in this case
这是因为LocalDateTime.from(TemporalAccessor temporal)
用于TemporalQueries.LOCAL_TIME
查询temporal
. TemporalQueries.LOCAL_TIME
反过来,需要ChronoField.NANO_OF_DAY
从 获得temporal
。
System.out.println(patternWithOptional.parse("4/11/2020 1:20"));
// prints:
{HourOfAmPm=1, MinuteOfHour=20},ISO resolved to 2020-04-11
由于HourOfAmPm
并且MinuteOfHour
可用,实现我需要的最简单的方法,我可以想出:
private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
.appendPattern("M/d/yyyy[ h:mm]")
.toFormatter();
public static void main(String[] args) {
// demo
System.out.println(parse("3/20/1995")); // without time
System.out.println(parse("4/11/2020 1:20")); // with time
}
private static LocalDateTime parse(String s) {
TemporalAccessor parsed = FORMATTER.parse(s);
return LocalDateTime.of(
LocalDate.from(parsed),
LocalTime.of(
parsed.isSupported(ChronoField.HOUR_OF_AMPM)
? (int) ChronoField.HOUR_OF_AMPM.getFrom(parsed)
: 0,
parsed.isSupported(ChronoField.MINUTE_OF_HOUR)
? (int) ChronoField.MINUTE_OF_HOUR.getFrom(parsed)
: 0
) // minor note: this part could also be used as a lambda argument for parseBest method.
);
}
isSupported
有没有更简单的方法可以在没有明确检查的情况下做到这一点?
解决方案
在您的格式模式字符串中,您需要在H
一天中的一小时内使用大写:
.appendPattern("M/d/yyyy[ H:mm]")
通过此更改,您的第一个片段打印
2020-04-11T01:20
LocalDateTime
小写h
是上午或下午内的小时。因此,您的时间可能意味着 01:20 AM 或 01:20 PM,即 13:20。Java 无法决定,因此选择不解释一天中的时间,只给你一个LocalDate
.
如果你总是想要一个LocalDateTime
,你也可以使用parseDefaulting
:
DateTimeFormatter patternWithOptional = new DateTimeFormatterBuilder()
.appendPattern("M/d/yyyy[ H:mm]")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.toFormatter();
System.out.println(LocalDateTime.parse("4/11/2020 1:20", patternWithOptional));
System.out.println(LocalDateTime.parse("4/11/2020", patternWithOptional));
输出:
2020-04-11T01:20
2020-04-11T00:00
另一方面,如果您确实需要 aLocalDate
或 a ,LocalDateTime
具体取决于字符串中是否有可用的时间,则不需要 a DateTimeFormatterBuilder
:
DateTimeFormatter patternWithOptional = DateTimeFormatter.ofPattern("M/d/yyyy[ H:mm]");
推荐阅读
- blockchain - 是否可以创建我们自己的 Solidity 库?
- haskell - Haskell如何添加可以处理Maybe列表的实例
- typescript - 打字稿可以处理不基于函数参数的动态返回类型吗?
- c# - 将电子邮件保存到具有指定文件名的目录在 .NET 5.0 中不起作用
- javascript - 创建和定义 JS 对象的属性和子属性
- c - 伯罗斯惠勒变换
- c++ - 在 C++ 问题中将时间字符串转换为秒
- java - 如何从文件中读取公钥
- openlayers - 使用 RGF93 / Lambert-93 渲染平铺矢量源的问题——法国坐标系
- python - 处理两个 excel 文件并将结果下载到烧瓶中的第三个 excel 文件中