简体   繁体   English

java 8中的通用日期和时间解析

[英]Generic date and time parsing in java 8

I was recently trying to make a generic date and time parsing method with the java 8 time API, mainly for interfacing with older code using Date .我最近尝试使用 java 8 time API 制作一个通用的日期和时间解析方法,主要用于使用Date与旧代码交互。

I wanted to do something like that:我想做这样的事情:

public static Date parse(String dateStr, String pattern) {
    return Date.from(Instant.parse(dateStr, DateTimeFormatter.ofPattern(pattern)));
}

The problem is that with the time API, the class to use depends on the pattern DateTimeFormatter.parse will never fail but will return a TemporalAccessor which is horrible to work with and convert to a usable class.问题在于,对于时间 API,要使用的类取决于模式DateTimeFormatter.parse永远不会失败,但会返回一个TemporalAccessor ,它很难使用并转换为可用的类。

And LocalDateTime.parse will fail if the pattern has no time information like "dd/MM/yyyy".如果模式没有像“dd/MM/yyyy”这样的时间信息, LocalDateTime.parse将失败。 Other classes like Instant , ZonedDateTime , etc. will all fail to parse if the pattern doesn't match the expected class.如果模式与预期的类不匹配,其他类如InstantZonedDateTime等都将无法解析。

Ideally, I'd like a way to parse leniently and return an Instant, with default values for missing fields, but I can't find a way to do that.理想情况下,我想要一种轻松解析并返回 Instant 的方法,其中缺少字段的默认值,但我找不到这样做的方法。

Any idea?任何想法?

You can use DateTimeFormatterBuilder::parseDefaulting to set default values.您可以使用DateTimeFormatterBuilder::parseDefaulting设置默认值。

var now = ZonedDateTime.now();
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendPattern(pattern)
    .parseDefaulting(ChronoField.OFFSET_SECONDS, now.getOffset().getTotalSeconds())
    .parseDefaulting(ChronoField.YEAR, now.getYear())
    .parseDefaulting(ChronoField.MONTH_OF_YEAR, now.getMonthValue())
    .parseDefaulting(ChronoField.DAY_OF_MONTH, now.getDayOfMonth())
    .parseDefaulting(ChronoField.HOUR_OF_DAY, now.getHour())
    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, now.getMinute())
    .parseDefaulting(ChronoField.SECOND_OF_MINUTE, now.getSecond())
    .toFormatter(Locale.ROOT);
Instant dt = Instant.from(formatter.parse(str));

Note that it's important to first append the pattern using appendPattern , and then set all your defaults using parseDefaulting .请注意,首先使用appendPattern附加模式很重要,然后使用parseDefaulting设置所有默认值。

Also note that I used the current time stamp to fill the defaults.另请注意,我使用当前时间戳来填充默认值。 So, for example, if you left out the year, it takes the current year (2022 at the time of writing).因此,例如,如果您遗漏了年份,则需要当前年份(撰写本文时为 2022 年)。 Of course, the defaults depend on your exact use case.当然,默认值取决于您的确切用例。

Examples:例子:

At the time of writing, it's 2022-06-09T17:18:36+02:00 .在撰写本文时,它是2022-06-09T17:18:36+02:00

System.out.println(parse("9-6", "d-M"));
System.out.println(parse("2023", "uuuu"));
System.out.println(parse("10:13", "H:m"));
System.out.println(parse("25 Dec, 16:22", "d MMM, H:mm"));

resolves to解决为

2022-06-09T15:18:36Z
2023-06-09T15:18:36Z
2022-06-09T08:13:36Z
2022-12-25T14:22:36Z

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM